On Thu, 27 Jun 2024 11:09:27 GMT, lingjun-cg <d...@openjdk.org> wrote:
>> ### Performance regression of DecimalFormat.format >> From the output of perf, we can see the hottest regions contain atomic >> instructions. But when run with JDK 11, there is no such problem. The >> reason is the removed biased locking. >> The DecimalFormat uses StringBuffer everywhere, and StringBuffer itself >> contains many synchronized methods. >> So I added support for some new methods that accept StringBuilder which is >> lock-free. >> >> ### Benchmark testcase >> >> @BenchmarkMode(Mode.AverageTime) >> @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) >> @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) >> @State(Scope.Thread) >> @OutputTimeUnit(TimeUnit.NANOSECONDS) >> public class JmhDecimalFormat { >> >> private DecimalFormat format; >> >> @Setup(Level.Trial) >> public void setup() { >> format = new DecimalFormat("#0.00000"); >> } >> >> @Benchmark >> public void testNewAndFormat() throws InterruptedException { >> new DecimalFormat("#0.00000").format(9524234.1236457); >> } >> >> @Benchmark >> public void testNewOnly() throws InterruptedException { >> new DecimalFormat("#0.00000"); >> } >> >> @Benchmark >> public void testFormatOnly() throws InterruptedException { >> format.format(9524234.1236457); >> } >> } >> >> >> ### Test result >> #### Current JDK before optimize >> >> Benchmark Mode Cnt Score Error Units >> JmhDecimalFormat.testFormatOnly avgt 50 642.099 ? 1.253 ns/op >> JmhDecimalFormat.testNewAndFormat avgt 50 989.307 ? 3.676 ns/op >> JmhDecimalFormat.testNewOnly avgt 50 303.381 ? 5.252 ns/op >> >> >> >> #### Current JDK after optimize >> >> Benchmark Mode Cnt Score Error Units >> JmhDecimalFormat.testFormatOnly avgt 50 351.499 ? 0.761 ns/op >> JmhDecimalFormat.testNewAndFormat avgt 50 615.145 ? 2.478 ns/op >> JmhDecimalFormat.testNewOnly avgt 50 209.874 ? 9.951 ns/op >> >> >> ### JDK 11 >> >> Benchmark Mode Cnt Score Error Units >> JmhDecimalFormat.testFormatOnly avgt 50 364.214 ? 1.191 ns/op >> JmhDecimalFormat.testNewAndFormat avgt 50 658.699 ? 2.311 ns/op >> JmhDecimalFormat.testNewOnly avgt 50 248.300 ? 5.158 ns/op > > lingjun-cg has updated the pull request incrementally with one additional > commit since the last revision: > > 8333396: Performance regression of DecimalFormat.format src/java.base/share/classes/java/text/CompactNumberFormat.java line 814: > 812: * @see FieldPosition > 813: */ > 814: private StringBuffer format(BigDecimal number, StringBuffer result, Can we update this private method's signature to `StringBuf` safely? src/java.base/share/classes/java/text/CompactNumberFormat.java line 909: > 907: * @see FieldPosition > 908: */ > 909: private StringBuffer format(BigInteger number, StringBuffer result, Same question, no need to keep StringBuffer signature in private methods test/micro/org/openjdk/bench/java/text/DefFormatterBench.java line 97: > 95: @Benchmark > 96: public void testDateFormat(final Blackhole blackhole) { > 97: blackhole.consume(dateFormat.format(date)); We usually just return the value if the blackhole only consumes one value. Blackhole is usually used for producing multiple values, such as running in a loop and ensure each iteration's result is used (as in testDefNumberFormatter) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/19513#discussion_r1657725192 PR Review Comment: https://git.openjdk.org/jdk/pull/19513#discussion_r1657725559 PR Review Comment: https://git.openjdk.org/jdk/pull/19513#discussion_r1657738836