On Wed, 6 Sep 2023 10:20:17 GMT, Quan Anh Mai <qa...@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