<i18n dev> RFR: 8365186: Reduce size of j.t.f.DateTimePrintContext::adjust
Shaojin Wen
swen at openjdk.org
Sat Aug 9 05:17:55 UTC 2025
On Tue, 5 Aug 2025 01:23:17 GMT, Shaojin Wen <swen at openjdk.org> wrote:
> By adding the JVM startup parameters `-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining` and analyzing the printed log information, and found that the code size of the j.t.f.DateTimePrintContext::adjust method is 382, which is greater than 325, causing inlining failure.
>
>
> @ 7 java.time.format.DateTimePrintContext::adjust (382 bytes) failed to inline: hot method too big
>
>
> By splitting the code into `common/uncommon`, and moving the uncommon code into adjust0, the adjust method is kept small and can be inlined by the C2 optimizer.
By running DateTimeFormatterBench, we can see that the current proposal can improve performance by about 5% in multiple scenarios. The detailed data is as follows
# 1. Running performance test scripts
# before
git checkout 158e59ab9184127089f9693ce256001f64b5945c
make test TEST="micro:java.time.format.DateTimeFormatterBench"
# after
git checkout 0278bba135bed6e99a9e9f99cb656275c27f8465
make test TEST="micro:java.time.format.DateTimeFormatterBench"
# 2. Performance results in multiple architectures
## 2.1. MacBook M1 Pro (aarch64)
-# before
-Benchmark (pattern) Mode Cnt Score Error Units
-DateTimeFormatterBench.formatInstants HH:mm:ss thrpt 15 15.053 ± 0.281 ops/ms
-DateTimeFormatterBench.formatInstants HH:mm:ss.SSS thrpt 15 10.664 ± 0.119 ops/ms
-DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss thrpt 15 8.994 ± 0.579 ops/ms
-DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 6.943 ± 0.370 ops/ms
-DateTimeFormatterBench.formatZonedDateTime HH:mm:ss thrpt 15 22.938 ± 0.056 ops/ms
-DateTimeFormatterBench.formatZonedDateTime HH:mm:ss.SSS thrpt 15 15.882 ± 0.144 ops/ms
-DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss thrpt 15 13.302 ± 0.518 ops/ms
-DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 10.153 ± 0.075 ops/ms
+# after
+Benchmark (pattern) Mode Cnt Score Error Units
+DateTimeFormatterBench.formatInstants HH:mm:ss thrpt 15 16.083 ± 0.178 ops/ms +6.84%
+DateTimeFormatterBench.formatInstants HH:mm:ss.SSS thrpt 15 11.548 ± 0.171 ops/ms +8.28%
+DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss thrpt 15 9.835 ± 0.064 ops/ms +9.35%
+DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 7.344 ± 0.308 ops/ms +5.77%
+DateTimeFormatterBench.formatZonedDateTime HH:mm:ss thrpt 15 22.500 ± 0.147 ops/ms -1.90%
+DateTimeFormatterBench.formatZonedDateTime HH:mm:ss.SSS thrpt 15 16.592 ± 0.086 ops/ms +4.47%
+DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss thrpt 15 13.182 ± 0.829 ops/ms -0.90%
+DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 10.127 ± 0.140 ops/ms -0.25%
## 2.2. aliyun_c8y (aarch64 CPU Aliyun_Yitian 710)
-# before
-Benchmark (pattern) Mode Cnt Score Error Units
-DateTimeFormatterBench.formatInstants HH:mm:ss thrpt 15 9.916 ± 0.073 ops/ms
-DateTimeFormatterBench.formatInstants HH:mm:ss.SSS thrpt 15 7.416 ± 0.013 ops/ms
-DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss thrpt 15 6.248 ± 0.082 ops/ms
-DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 4.988 ± 0.042 ops/ms
-DateTimeFormatterBench.formatZonedDateTime HH:mm:ss thrpt 15 13.653 ± 0.073 ops/ms
-DateTimeFormatterBench.formatZonedDateTime HH:mm:ss.SSS thrpt 15 9.435 ± 0.033 ops/ms
-DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss thrpt 15 7.550 ± 0.145 ops/ms
-DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 6.096 ± 0.301 ops/ms
+# after
+Benchmark (pattern) Mode Cnt Score Error Units
+DateTimeFormatterBench.formatInstants HH:mm:ss thrpt 15 10.897 ± 0.047 ops/ms +9.89%
+DateTimeFormatterBench.formatInstants HH:mm:ss.SSS thrpt 15 7.449 ± 0.086 ops/ms +0.44%
+DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss thrpt 15 6.979 ± 0.025 ops/ms +11.69%
+DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 4.950 ± 0.024 ops/ms -0.76%
+DateTimeFormatterBench.formatZonedDateTime HH:mm:ss thrpt 15 14.206 ± 0.206 ops/ms +4.05%
+DateTimeFormatterBench.formatZonedDateTime HH:mm:ss.SSS thrpt 15 9.957 ± 0.182 ops/ms +5.53%
+DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss thrpt 15 7.705 ± 0.093 ops/ms +2.05%
+DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 6.222 ± 0.235 ops/ms +2.06%
## 2.3. OrangePi 5 (aarch64 CPU RK3588)
-# before
-Benchmark (pattern) Mode Cnt Score Error Units
-DateTimeFormatterBench.formatInstants HH:mm:ss thrpt 15 6.118 ± 0.417 ops/ms
-DateTimeFormatterBench.formatInstants HH:mm:ss.SSS thrpt 15 4.312 ± 0.202 ops/ms
-DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss thrpt 15 4.047 ± 0.107 ops/ms
-DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 2.773 ± 0.204 ops/ms
-DateTimeFormatterBench.formatZonedDateTime HH:mm:ss thrpt 15 9.228 ± 0.232 ops/ms
-DateTimeFormatterBench.formatZonedDateTime HH:mm:ss.SSS thrpt 15 5.640 ± 0.223 ops/ms
-DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss thrpt 15 5.109 ± 0.076 ops/ms
-DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 3.407 ± 0.168 ops/ms
+# after
+Benchmark (pattern) Mode Cnt Score Error Units
+DateTimeFormatterBench.formatInstants HH:mm:ss thrpt 15 6.080 ± 0.451 ops/ms -0.62%
+DateTimeFormatterBench.formatInstants HH:mm:ss.SSS thrpt 15 4.341 ± 0.219 ops/ms +0.67%
+DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss thrpt 15 4.009 ± 0.207 ops/ms -0.93%
+DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 2.928 ± 0.104 ops/ms +5.58%
+DateTimeFormatterBench.formatZonedDateTime HH:mm:ss thrpt 15 9.670 ± 0.139 ops/ms +4.78%
+DateTimeFormatterBench.formatZonedDateTime HH:mm:ss.SSS thrpt 15 5.835 ± 0.234 ops/ms +3.45%
+DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss thrpt 15 5.149 ± 0.153 ops/ms +0.78%
+DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 3.553 ± 0.131 ops/ms +4.28%
## 2.4 aliyun_c9i (x64 CPU Intel Xeon Granite Rapids)
-# before
-Benchmark (pattern) Mode Cnt Score Error Units
-DateTimeFormatterBench.formatInstants HH:mm:ss thrpt 15 15.718 ± 1.343 ops/ms
-DateTimeFormatterBench.formatInstants HH:mm:ss.SSS thrpt 15 11.758 ± 0.638 ops/ms
-DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss thrpt 15 10.529 ± 0.057 ops/ms
-DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 7.945 ± 0.304 ops/ms
-DateTimeFormatterBench.formatZonedDateTime HH:mm:ss thrpt 15 20.441 ± 0.067 ops/ms
-DateTimeFormatterBench.formatZonedDateTime HH:mm:ss.SSS thrpt 15 13.975 ± 0.062 ops/ms
-DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss thrpt 15 11.721 ± 0.070 ops/ms
-DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 8.604 ± 0.073 ops/ms
+# after
+Benchmark (pattern) Mode Cnt Score Error Units
+DateTimeFormatterBench.formatInstants HH:mm:ss thrpt 15 16.745 ± 0.129 ops/ms +6.53%
+DateTimeFormatterBench.formatInstants HH:mm:ss.SSS thrpt 15 11.571 ± 1.085 ops/ms -1.52%
+DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss thrpt 15 10.591 ± 0.046 ops/ms +0.58%
+DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 7.899 ± 0.323 ops/ms -0.57%
+DateTimeFormatterBench.formatZonedDateTime HH:mm:ss thrpt 15 20.993 ± 0.082 ops/ms +2.70%
+DateTimeFormatterBench.formatZonedDateTime HH:mm:ss.SSS thrpt 15 14.123 ± 0.094 ops/ms +1.05%
+DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss thrpt 15 11.781 ± 0.054 ops/ms +0.51%
+DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 8.723 ± 0.055 ops/ms +1.38%
## 2.5 MacBook 2019 (x64 intel i9)
-# before
-Benchmark (pattern) Mode Cnt Score Error Units
-DateTimeFormatterBench.formatInstants HH:mm:ss thrpt 15 12.393 ± 0.985 ops/ms
-DateTimeFormatterBench.formatInstants HH:mm:ss.SSS thrpt 15 9.658 ± 0.220 ops/ms
-DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss thrpt 15 8.321 ± 0.098 ops/ms
-DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 6.575 ± 0.073 ops/ms
-DateTimeFormatterBench.formatZonedDateTime HH:mm:ss thrpt 15 18.946 ± 0.387 ops/ms
-DateTimeFormatterBench.formatZonedDateTime HH:mm:ss.SSS thrpt 15 12.156 ± 0.316 ops/ms
-DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss thrpt 15 9.980 ± 0.115 ops/ms
-DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 7.729 ± 0.160 ops/ms
+# after
+Benchmark (pattern) Mode Cnt Score Error Units
+DateTimeFormatterBench.formatInstants HH:mm:ss thrpt 15 13.942 ± 0.257 ops/ms +12.49%
+DateTimeFormatterBench.formatInstants HH:mm:ss.SSS thrpt 15 9.882 ± 0.327 ops/ms +2.42%
+DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss thrpt 15 9.234 ± 0.240 ops/ms +10.97%
+DateTimeFormatterBench.formatInstants yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 6.594 ± 0.074 ops/ms +2.89%
+DateTimeFormatterBench.formatZonedDateTime HH:mm:ss thrpt 15 19.482 ± 0.385 ops/ms +2.82%
+DateTimeFormatterBench.formatZonedDateTime HH:mm:ss.SSS thrpt 15 12.917 ± 0.244 ops/ms +6.26%
+DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss thrpt 15 10.196 ± 0.142 ops/ms +2.16%
+DateTimeFormatterBench.formatZonedDateTime yyyy-MM-dd'T'HH:mm:ss.SSS thrpt 15 7.793 ± 0.136 ops/ms +8.28%
* Run the test script
make test TEST="micro:java.time.format.DateTimeFormatterWithPaddingBench"
* Test results on aliyun_c9i (x64 CPU Intel Xeon Granite Rapids)
-# before
-Benchmark Mode Cnt Score Error Units
-DateTimeFormatterWithPaddingBench.formatWithPadding thrpt 15 11823.795 ± 221.488 ops/ms
-DateTimeFormatterWithPaddingBench.formatWithPaddingLengthOne thrpt 15 34634.499 ± 91.144 ops/ms
-DateTimeFormatterWithPaddingBench.formatWithPaddingLengthZero thrpt 15 39070.959 ± 198.192 ops/ms
+# after
+Benchmark Mode Cnt Score Error Units
+DateTimeFormatterWithPaddingBench.formatWithPadding thrpt 15 12257.729 ± 49.449 ops/ms +3.67%
+DateTimeFormatterWithPaddingBench.formatWithPaddingLengthOne thrpt 15 37689.494 ± 117.526 ops/ms +8.82%
+DateTimeFormatterWithPaddingBench.formatWithPaddingLengthZero thrpt 15 43628.181 ± 493.395 ops/ms +11.66%
In DateTimeFormatterWithPaddingBench, I found that this proposal improved performance even more.
This is because DateTimeFormatter is statically defined as final, and DateTimeFormatter::getChronology and DateTimeFormatter::getZone used in the adjust method are final fields. This eliminates dead code branches during inlining by the C2 optimizer.
* The following code is the formatter definition in DateTimeFormatterWithPaddingBench. The modifiers of the fields FORMATTER_WITH_PADDING/FORMATTER_WITH_PADDING_ZERO/FORMATTER_WITH_PADDING_ONE are static final.
public class DateTimeFormatterWithPaddingBench {
private static final DateTimeFormatter FORMATTER_WITH_PADDING = new DateTimeFormatterBuilder()
.appendLiteral("Date:")
.padNext(20, ' ')
.append(DateTimeFormatter.ISO_DATE)
.toFormatter();
private static final DateTimeFormatter FORMATTER_WITH_PADDING_ZERO = new DateTimeFormatterBuilder()
.appendLiteral("Year:")
.padNext(4)
.appendValue(ChronoField.YEAR)
.toFormatter();
private static final DateTimeFormatter FORMATTER_WITH_PADDING_ONE = new DateTimeFormatterBuilder()
.appendLiteral("Year:")
.padNext(5)
.appendValue(ChronoField.YEAR)
.toFormatter();
* In the DateTimeFormatter related code, the modifiers of the chrono/zone fields are also final
final class DateTimeFormatter {
private final Chronology chrono;
private final ZoneId zone;
public Chronology getChronology() {
return chrono;
}
public ZoneId getZone() {
return zone;
}
}
* The following code in the DateTimePrintContext::adjust method uses chrono and zone. When adjust can be inlined, dead code branches can be eliminated to improve performance.
final class DateTimePrintContext {
private static TemporalAccessor adjust(final TemporalAccessor temporal, DateTimeFormatter formatter) {
Chronology overrideChrono = formatter.getChronology();
ZoneId overrideZone = formatter.getZone();
if (overrideChrono == null && overrideZone == null) {
return temporal;
}
// ....
}
}
-------------
PR Comment: https://git.openjdk.org/jdk/pull/26633#issuecomment-3155866814
PR Comment: https://git.openjdk.org/jdk/pull/26633#issuecomment-3158585653
More information about the i18n-dev
mailing list