Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions src/java.base/share/classes/java/util/UUID.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

import jdk.internal.access.JavaLangAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.util.ByteArray;
import jdk.internal.util.ByteArrayLittleEndian;
import jdk.internal.util.HexDigits;

/**
Expand Down Expand Up @@ -470,34 +470,34 @@ public String toString() {
long lsb = leastSigBits;
long msb = mostSigBits;
byte[] buf = new byte[36];
ByteArray.setLong(
ByteArrayLittleEndian.setLong(
buf,
0,
HexDigits.digit((int) (msb >> 56), (int) (msb >> 48), (int) (msb >> 40), (int) (msb >> 32)));
HexDigits.packDigits((int) (msb >> 56), (int) (msb >> 48), (int) (msb >> 40), (int) (msb >> 32)));
buf[8] = '-';
ByteArray.setInt(
ByteArrayLittleEndian.setInt(
buf,
9,
HexDigits.digit(((int) msb) >> 24, ((int) msb) >> 16));
HexDigits.packDigits(((int) msb) >> 24, ((int) msb) >> 16));
buf[13] = '-';
ByteArray.setInt(
ByteArrayLittleEndian.setInt(
buf,
14,
HexDigits.digit(((int) msb) >> 8, (int) msb));
HexDigits.packDigits(((int) msb) >> 8, (int) msb));
buf[18] = '-';
ByteArray.setInt(
ByteArrayLittleEndian.setInt(
buf,
19,
HexDigits.digit((int) (lsb >> 56), (int) (lsb >> 48)));
HexDigits.packDigits((int) (lsb >> 56), (int) (lsb >> 48)));
buf[23] = '-';
ByteArray.setLong(
ByteArrayLittleEndian.setLong(
buf,
24,
HexDigits.digit(((int) (lsb >> 40)), (int) (lsb >> 32), ((int) lsb) >> 24, ((int) lsb) >> 16));
ByteArray.setInt(
HexDigits.packDigits((int) (lsb >> 40), (int) (lsb >> 32), ((int) lsb) >> 24, ((int) lsb) >> 16));
ByteArrayLittleEndian.setInt(
buf,
32,
HexDigits.digit(((int) lsb) >> 8, (int) lsb));
HexDigits.packDigits(((int) lsb) >> 8, (int) lsb));

try {
return jla.newStringNoRepl(buf, StandardCharsets.ISO_8859_1);
Expand Down
67 changes: 30 additions & 37 deletions src/java.base/share/classes/jdk/internal/util/HexDigits.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,38 +39,27 @@ public final class HexDigits implements Digits {
* Each element of the array represents the ascii encoded
* hex relative to its index, for example:<p>
* <pre>
* 0 -> '00' -> ('0' << 8) | '0' -> 12336
* 1 -> '01' -> ('0' << 8) | '1' -> 12337
* 2 -> '02' -> ('0' << 8) | '2' -> 12338
* 0 -> '00' -> '0' | ('0' << 8) -> 0x3030
* 1 -> '01' -> '0' | ('1' << 8) -> 0x3130
* 2 -> '02' -> '0' | ('2' << 8) -> 0x3230
*
* ...
*
* 10 -> '0a' -> ('0' << 8) | 'a' -> 12385
* 11 -> '0b' -> ('0' << 8) | 'b' -> 12386
* 12 -> '0c' -> ('0' << 8) | 'b' -> 12387
* 10 -> '0a' -> '0' | ('a' << 8) -> 0x6130
* 11 -> '0b' -> '0' | ('b' << 8) -> 0x6230
* 12 -> '0c' -> '0' | ('b' << 8) -> 0x6330
*
* ...
*
* 26 -> '1a' -> ('1' << 8) | 'a' -> 12641
* 27 -> '1b' -> ('1' << 8) | 'b' -> 12642
* 28 -> '1c' -> ('1' << 8) | 'c' -> 12643
* 26 -> '1a' -> '1' | ('a' << 8) -> 0x6131
* 27 -> '1b' -> '1' | ('b' << 8) -> 0x6231
* 28 -> '1c' -> '1' | ('c' << 8) -> 0x6331
*
* ...
*
* 253 -> 'fd' -> ('f' << 8) | 'd' -> 26212
* 254 -> 'fe' -> ('f' << 8) | 'e' -> 26213
* 255 -> 'ff' -> ('f' << 8) | 'f' -> 26214
* </pre>
* <p>use like this:
* <pre>
* int v = 254;
*
* char[] chars = new char[2];
*
* short i = DIGITS[v]; // 26213
*
* chars[0] = (char) (byte) (i >> 8); // 'f'
* chars[1] = (char) (byte) i; // 'e'
* 253 -> 'fd' -> 'f' | ('d' << 8) -> 0x6466
* 254 -> 'fe' -> 'f' | ('e' << 8) -> 0x6566
* 255 -> 'ff' -> 'f' | ('f' << 8) -> 0x6666
* </pre>
*/
@Stable
Expand All @@ -85,10 +74,10 @@ public final class HexDigits implements Digits {
short[] digits = new short[16 * 16];

for (int i = 0; i < 16; i++) {
short hi = (short) ((i < 10 ? i + '0' : i - 10 + 'a') << 8);
short lo = (short) (i < 10 ? i + '0' : i - 10 + 'a');

for (int j = 0; j < 16; j++) {
short lo = (short) (j < 10 ? j + '0' : j - 10 + 'a');
short hi = (short) ((j < 10 ? j + '0' : j - 10 + 'a') << 8);
digits[(i << 4) + j] = (short) (hi | lo);
}
}
Expand All @@ -103,20 +92,24 @@ private HexDigits() {
}

/**
* Combine two hex shorts into one int based on big endian
* Return a little-endian packed integer for the 4 ASCII bytes for an input unsigned 2-byte integer.
* {@code b0} is the most significant byte and {@code b1} is the least significant byte.
* The integer is passed byte-wise to allow reordering of execution.
*/
public static int digit(int b0, int b1) {
return (DIGITS[b0 & 0xff] << 16) | DIGITS[b1 & 0xff];
public static int packDigits(int b0, int b1) {
return DIGITS[b0 & 0xff] | (DIGITS[b1 & 0xff] << 16);
}

/**
* Combine four hex shorts into one long based on big endian
* Return a little-endian packed long for the 8 ASCII bytes for an input unsigned 4-byte integer.
* {@code b0} is the most significant byte and {@code b3} is the least significant byte.
* The integer is passed byte-wise to allow reordering of execution.
*/
public static long digit(int b0, int b1, int b2, int b3) {
return (((long) DIGITS[b0 & 0xff]) << 48)
| (((long) DIGITS[b1 & 0xff]) << 32)
| (DIGITS[b2 & 0xff] << 16)
| DIGITS[b3 & 0xff];
public static long packDigits(int b0, int b1, int b2, int b3) {
return DIGITS[b0 & 0xff]
| (DIGITS[b1 & 0xff] << 16)
| (((long) DIGITS[b2 & 0xff]) << 32)
| (((long) DIGITS[b3 & 0xff]) << 48);
Comment on lines +109 to +112
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you reverse the order of these source lines to put the shifts of the higher order bits before the lower order bit shifts. 3333222211110000. Its easier to understand where the bits end up in the long.
The rest of the change is better focused.

Copy link
Contributor Author

@wenshao wenshao Sep 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if reverse packDigits order, performance will be slow, I don't know why yet.

The following is the data running on MacBookPro M1 Max :

make test TEST="micro:java.util.UUIDBench.toString"

Benchmark           (size)   Mode  Cnt   Score   Error   Units (current order 4f6ed3e6)
UUIDBench.toString   20000  thrpt   15  96.396 ? 0.946  ops/us


Benchmark           (size)   Mode  Cnt   Score   Error   Units (reverse packDigits order)
UUIDBench.toString   20000  thrpt   15  86.496 ? 0.542  ops/us

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like something that might be an interesting puzzler for JIT compiler folks. Perhaps added implicit casts to long messes something up?

}

@Override
Expand All @@ -125,15 +118,15 @@ public int digits(long value, byte[] buffer, int index,
while ((value & ~0xFF) != 0) {
int digits = DIGITS[(int) (value & 0xFF)];
value >>>= 8;
putCharMH.invokeExact(buffer, --index, digits & 0xFF);
putCharMH.invokeExact(buffer, --index, digits >> 8);
putCharMH.invokeExact(buffer, --index, digits & 0xFF);
}

int digits = DIGITS[(int) (value & 0xFF)];
putCharMH.invokeExact(buffer, --index, digits & 0xFF);
putCharMH.invokeExact(buffer, --index, digits >> 8);

if (0xF < value) {
putCharMH.invokeExact(buffer, --index, digits >> 8);
putCharMH.invokeExact(buffer, --index, digits & 0xFF);
}

return index;
Expand Down