RFR (S) 8136500: Integer/Long getChars and stringSize should be more idiomatic
Peter Levart
peter.levart at gmail.com
Tue Nov 24 17:11:45 UTC 2015
On 11/24/2015 05:50 PM, Ulf wrote:
> Hi,
>
> Am 24.11.2015 um 12:07 schrieb Aleksey Shipilev:
>> Thanks for reviews, Ivan, John, Sherman and Paul!
>>
>> I am pushing this change now.
>
> I know, I'm late, but have you ever tried? :
>
> static void getChars(int i, int index, byte[] buf) {
> // int q, r; // superfluous
> // int charPos = index; // superfluous
> boolean negative = i < 0;
>
> // Generate two digits per iteration // q and r are not
> needed outside loop
> for (int q, i = negative ? i : -i; <= -100; i = q) {
> q = i / 100;
> byte r = (byte)((q * 100 - i) & 0x7F);
> // byte allows the compiler to use byte wide addressing
> opcodes
> // which have smaller footprint and are potentially faster
> // .. & 0x7F may additionally save negative bound check
> buf[(byte)(--index & 0x7F)] = DigitOnes[r];
> buf[(byte)(--index & 0x7F)] = DigitTens[r];
...but index can be large and overflow byte range. Imagine concatenating
into a String with target length > 127 ...
> }
>
> // We know there are at most two digits left at this point.
> byte q = (byte)i / 10;
> buf[(byte)(--index & 0x7F)] = (byte)(q * 10 - i +'0');
>
> // Whatever left is the remaining digit.
> if (q < 0) {
> buf[(byte)(--index & 0x7F)] = (byte)('0' - q);
> }
> if (negative) {
> buf[(byte)(--index & 0x7F)] = (byte)'-';
> }
> }
>
> Additionally may try this:
> (saves some calculations, but adds array access, only 1 for more
> frequent i < 10, otherwise 2)
> // We know there are at most two digits left at this point.
> byte r = (byte)(-i & 0x7F);
> buf[(byte)(--index & 0x7F)] = DigitOnes[r];
>
> // Whatever left is the remaining digit.
> if (r >= 10) {
> buf[(byte)(--index & 0x7F)] = DigitTens[r];
> }
> if (negative) {
> buf[(byte)(--index & 0x7F)] = (byte)'-';
> }
>
>
>> 2)
>> The lookup tables DigitTens and DigitOnes are always used together.
>> Packing them in an one table can save us one array access for the
>> price of little arithmetic.
>>
>> static final int[] TwoDigits = {
>> ('0'<<16)+'0', ('0'<<16)+'1', ('0'<<16)+'2', ('0'<<16)+'3',
>> ('0'<<16)+'4',
>> ('0'<<16)+'5', ('0'<<16)+'6', ('0'<<16)+'7', ('0'<<16)+'8',
>> ('0'<<16)+'9',
>>
>> ...
>> int twoDig = TwoDigits[r];
>> buf[--charPos] = (byte)twoDig;
>> buf[--charPos] = (byte)(twoDig >> 16);
>> ...
>
> This could be done faster if using 1 "Unsafe putChar/Short()" instead
> 2 buf[--charPos] + shift.
> ... and better use char/short[] to save footprint and the compiler
> calculating the table offset with charPos<<1.
>
> Alternatively use byte[] TwoDigits =
> useInternalCompactByteArrayOfString("00010203040506070809....")
>
> -Ulf
>
More information about the core-libs-dev
mailing list