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

Reply via email to