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

Reply via email to