RFR: 8310929: Optimization for Integer.toString [v20]
温绍锦
duke at openjdk.org
Wed Sep 6 14:41:44 UTC 2023
On Wed, 6 Sep 2023 10:20:17 GMT, Quan Anh Mai <qamai at openjdk.org> wrote:
> We can consolidate the implementation of `Integer::toString` and `Integer::toUnsignedString` by taking the absolute value of the signed integer and move the later operation to unsigned domain. This helps remove the need of relying on much more expensive `BigInteger` when invoking `Long::toUnsignedString` and may improve the performance of `Integer::toUnsignedString` a little bit. Computing in unsigned domain is also faster (`x s/ 100 = (x * 1374389535) >> 37 - (x >> 31)` while `x u/ 100 = (x * 1374389535) >>> 37`). Folding of unsigned division is still in review but we can use `(int)(((long)x * 1374389535) >>> 37)` for `int` and `mulhi(x >>> 2, 2951479051793528259) >>> 2` for `long` directly.
>
> Thanks.
According to your suggestion, I tested the following code, and the performance has not improved. I'm not sure this implementation is what you think.
static final byte[] INTEGER_MIN_BYTES = new byte[] {45, 50, 49, 52, 55, 52, 56, 51, 54, 52, 56};
static int getChars(int i, int index, byte[] buf) {
// Used by trusted callers. Assumes all necessary bounds checks have been done by the caller.
int q, r;
int charPos = index;
if (i == Integer.MIN_VALUE) {
int len = INTEGER_MIN_BYTES.length;
System.arraycopy(INTEGER_MIN_BYTES, 0, buf, index - len, len);
return index - len;
}
boolean negative = i < 0;
if (negative) {
i = -i;
}
// Generate two digits per iteration
while (i >= 100) {
// really: q = i / 100
q = (int) ((((long) i) * 1374389535) >>> 37);
r = i - (q * 100);
i = q;
charPos -= 2;
assert charPos >= 0 && charPos < buf.length : "Trusted caller missed bounds check";
UNSAFE.putShortUnaligned(buf, Unsafe.ARRAY_BYTE_BASE_OFFSET + charPos, PACKED_DIGITS[r], false);
}
// We know there are at most two digits left at this point.
if (i > 9) {
charPos -= 2;
assert charPos >= 0 && charPos < buf.length : "Trusted caller missed bounds check";
UNSAFE.putShortUnaligned(buf, Unsafe.ARRAY_BYTE_BASE_OFFSET + charPos, PACKED_DIGITS[i], false);
} else {
buf[--charPos] = (byte)('0' + i);
}
if (negative) {
buf[--charPos] = (byte)'-';
}
return charPos;
}
-------------
PR Comment: https://git.openjdk.org/jdk/pull/14699#issuecomment-1708502965
More information about the core-libs-dev
mailing list