On Fri, 5 Jul 2024 15:40:24 GMT, Shaojin Wen <d...@openjdk.org> wrote:
> String.format is widely used, and improving its performance is very > meaningful. This PR can significantly improve the performance of > String.format. Sorry, there are many changes, which will take a lot of time. > I hope you can review it patiently. > > > Improved performance includes the following: > > ## 1. Write directly during the parse process to reduce object allocation. > > In the current Formatter implementation, some objects do not need to be > allocated, such as: > > > class Formatter { > public Formatter format(Locale l, String format, Object ... args) { > List<FormatString> fsa = parse(format); > // ... > } > > static List<FormatString> parse(String s) { > ArrayList<FormatString> al = new ArrayList<>(); > > while (i < max) { > int n = s.indexOf('%', i); > if (n < 0) { > // > al.add(new FixedString(s, i, max)); > } > } > } > } > > In the process of parsing, the content that is not a Specifier is directly > appended without going through FixedString. By directly printing the parsed > FormatString object, there is no need to construct a `List<FormatString> fsa` > to store it. > > ## 2. Fast path print > Use specialized FormatString implementations for single-character and > single-width specifiers to avoid calling the large FormatSpecifier#print > method. > > ## 3. String.format directly calls j.u.Formatter > String.format directly calls j.u.Formatter via SharedSecrets to improve > performance src/java.base/share/classes/java/lang/String.java line 4548: > 4546: } > 4547: > 4548: private static class StringFormat { Since we want to avoid new classes on startup, we should change the lazy initialization pattern to: private static @Stable JavaUtilFormatterAccess jufa; private static JavaUtilFormatterAccess formatterAccess() { var access = jufa; if (access = null) { // We can assert not null on the getJUFA result return jufa = SharedSecrets.getJavaUtilFormatterAccess(); } return access; } using benign race. src/java.base/share/classes/java/util/Formatter.java line 3107: > 3105: if (fmt.locale() != l) > 3106: fmt = new Formatter(fmt.out(), l); > 3107: ((Formattable)arg).formatTo(fmt, Flags.NONE, -1, -1); You can use pattern matching for instanceof to avoid a cast here. src/java.base/share/classes/java/util/Formatter.java line 5260: > 5258: } > 5259: > 5260: static final FormatString[] specifiers = new FormatString[128]; Suggestion: static final @Stable FormatString[] specifiers = new FormatString[128]; ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/20055#discussion_r1667064117 PR Review Comment: https://git.openjdk.org/jdk/pull/20055#discussion_r1667087769 PR Review Comment: https://git.openjdk.org/jdk/pull/20055#discussion_r1667091143