8336741: Optimize LocalTime.toString with StringBuilder.repeat

Reviewed-by: liach, rriggs, naoto
This commit is contained in:
Shaojin Wen 2024-07-24 22:39:49 +00:00 committed by Chen Liang
parent 24f67d0254
commit 0898ab7f74
3 changed files with 166 additions and 8 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -92,6 +92,8 @@ import java.time.temporal.UnsupportedTemporalTypeException;
import java.time.temporal.ValueRange;
import java.util.Objects;
import jdk.internal.util.DecimalDigits;
/**
* A time without a time-zone in the ISO-8601 calendar system,
* such as {@code 10:15:30}.
@ -1640,13 +1642,19 @@ public final class LocalTime
buf.append(secondValue < 10 ? ":0" : ":").append(secondValue);
if (nanoValue > 0) {
buf.append('.');
if (nanoValue % 1000_000 == 0) {
buf.append(Integer.toString((nanoValue / 1000_000) + 1000).substring(1));
} else if (nanoValue % 1000 == 0) {
buf.append(Integer.toString((nanoValue / 1000) + 1000_000).substring(1));
} else {
buf.append(Integer.toString((nanoValue) + 1000_000_000).substring(1));
int zeros = 9 - DecimalDigits.stringSize(nanoValue);
if (zeros > 0) {
buf.repeat('0', zeros);
}
int digits;
if (nanoValue % 1_000_000 == 0) {
digits = nanoValue / 1_000_000;
} else if (nanoValue % 1000 == 0) {
digits = nanoValue / 1000;
} else {
digits = nanoValue;
}
buf.append(digits);
}
}
return buf.toString();

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -84,4 +84,30 @@ public final class DecimalDigits {
public static short digitPair(int i) {
return DIGITS[i];
}
/**
* Returns the string representation size for a given int value.
*
* @param x int value
* @return string size
*
* @implNote There are other ways to compute this: e.g. binary search,
* but values are biased heavily towards zero, and therefore linear search
* wins. The iteration results are also routinely inlined in the generated
* code after loop unrolling.
*/
public static int stringSize(int x) {
int d = 1;
if (x >= 0) {
d = 0;
x = -x;
}
int p = -10;
for (int i = 1; i < 10; i++) {
if (x > p)
return i + d;
p = 10 * p;
}
return 10 + d;
}
}