Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 6642323
Votes 0
Synopsis Speeding up Single Byte Decoders
Category java:char_encodings
Reported Against
Release Fixed 7(b43)
State 10-Fix Delivered, bug
Priority: 3-Medium
Related Bugs 6798572
Submit Date 15-DEC-2007
Description
Here's the critical decoder loop for ASCII

	private CoderResult decodeArrayLoop(ByteBuffer src,
					    CharBuffer dst)
	{
	    byte[] sa = src.array();
	    int sp = src.arrayOffset() + src.position();
	    int sl = src.arrayOffset() + src.limit();
	    assert (sp <= sl);
	    sp = (sp <= sl ? sp : sl);
	    char[] da = dst.array();
	    int dp = dst.arrayOffset() + dst.position();
	    int dl = dst.arrayOffset() + dst.limit();
	    assert (dp <= dl);
	    dp = (dp <= dl ? dp : dl);

	    try {
		while (sp < sl) {
		    byte b = sa[sp];
		    if (b >= 0) {
			if (dp >= dl)
			    return CoderResult.OVERFLOW;
			da[dp++] = (char)b;
			sp++;
			continue;
		    }
		    return CoderResult.malformedForLength(1);
		}
		return CoderResult.UNDERFLOW;
	    } finally {
		src.position(sp - src.arrayOffset());
		dst.position(dp - dst.arrayOffset());
	    }
	}


We can optimize the inner loop by checking for overflow and underflow at the same time.


        private static CoderResult normalResult(ByteBuffer src, int sp,
                                                CharBuffer dst, int dp) {
            updateBufferPositions(src, sp, dst, dp);
            return src.hasRemaining() ?
                CoderResult.OVERFLOW :
                CoderResult.UNDERFLOW;
        }

	private CoderResult decodeArrayLoop(ByteBuffer src,
					    CharBuffer dst)
	{
	    byte[] sa = src.array();
	    int sp = src.arrayOffset() + src.position();
	    int sl = src.arrayOffset() + src.limit();

            char[] da = dst.array();
	    int dp = dst.arrayOffset() + dst.position();
            int dl = dp + Math.min(src.remaining(),
                                   dst.remaining());
            while (dp < dl) {
                byte b = sa[sp];
                if (b >= 0) {
                    da[dp++] = (char)b;
                    sp++;
                } else
                    return coderResult(CoderResult.malformedForLength(1),
                                       src, sp, dst, dp);
            }
            return normalResult(src, sp, dst, dp);
        }
 

Similarly, for ISO-8859-1, we can optimize thus:

            int dl = dp + Math.min(src.remaining(),
                                   dst.remaining());
            while (dp < dl) {
                da[dp++] = (char)(sa[sp++] & 0xff);
            }
            return normalResult(src, sp, dst, dp);

For other table-driven single byte decoders, 
we can index into a char array instead of adding
a degree of indirection by indexing into a String.
If all bytes are valid, we can eliminate a check for unmappable
characters.  For e.g. ISO-8859-15, we are left with the tight inner loop

             while (dp < dl) {
                da[dp++] = byteToChar[sa[sp++] & 0xff];
            }

Simple benchmarking shows approximately a factor of two speedup
of decoding of long random byte sequences.
Posted Date : 2007-12-15 01:50:31.0
Work Around
N/A
Evaluation
Yes.
Posted Date : 2007-12-15 01:50:31.0

The benchmark from the latest mapping based new sbcs implementation, not all "tricks" suggested have been applied, but the performance looks much better.

                             old-client    old-server    new-client    new-server
------------------
Decoding 1b cp1252 :           4811 1.000     905 1.000    1965 1.000     746 1.000
Decoding 1b (direct)cp1252 :   9777 2.032    2717 3.001    7223 3.675    2773 3.718
Encoding 1b cp1252 :           4180 0.869    2710 2.994    3034 1.544    1544 2.070
Encoding 1b (direct)cp1252 :   9788 2.034    3521 3.889    7971 4.056    2612 3.502
------------------
Decoding 1b cp1252 :           4834 1.000     907 1.000    1964 1.000    745 1.000
Decoding 1b (direct)cp1252 :   9995 2.068    2710 2.987    7249 3.691    2775 3.724
Encoding 1b cp1252 :           4182 0.865    2707 2.984    2526 1.286    1548 2.077
Encoding 1b (direct)cp1252 :   9757 2.018    3521 3.881    7970 4.058    2609 3.502
------------------                                                        
Decoding 1b cp1252 :           4915 1.000     906 1.000    1965 1.000    765 1.000
Decoding 1b (direct)cp1252 :   9700 1.973    2707 2.985    7250 3.690    2770 3.618
Encoding 1b cp1252 :           4207 0.856    2706 2.984    3239 1.648    1545 2.019
Encoding 1b (direct)cp1252 :   9894 2.013    3521 3.884    7974 4.058    2609 3.408
Posted Date : 2008-12-10 22:14:42.0
Comments
  
  Include a link with my name & email   

Submitted On 15-DEC-2008
Some little faster:
        int sp = src.arrayOffset() + src.position();
        int sl = sp + src.remaining();



PLEASE NOTE: JDK6 is formerly known as Project Mustang