RFR (S) 8136500: Integer/Long getChars and stringSize should be more idiomatic
Ulf
Ulf.Zibis at CoSoCo.de
Tue Nov 24 16:50:11 UTC 2015
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];
}
// 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