On Wed, 27 Sep 2023 19:51:25 GMT, Raffaello Giulietti <rgiulie...@openjdk.org> 
wrote:

>> @cl4es made performance optimizations for the simple specifiers of 
>> String.format in PR https://github.com/openjdk/jdk/pull/2830. Based on the 
>> same idea, I continued to make improvements. I made patterns like %2d %02d 
>> also be optimized.
>> 
>> The following are the test results based on MacBookPro M1 Pro: 
>> 
>> 
>> -Benchmark                          Mode  Cnt     Score     Error  Units
>> -StringFormat.complexFormat         avgt   15  1862.233 ? 217.479  ns/op
>> -StringFormat.int02Format           avgt   15   312.491 ?  26.021  ns/op
>> -StringFormat.intFormat             avgt   15    84.432 ?   4.145  ns/op
>> -StringFormat.longFormat            avgt   15    87.330 ?   6.111  ns/op
>> -StringFormat.stringFormat          avgt   15    63.985 ?  11.366  ns/op
>> -StringFormat.stringIntFormat       avgt   15    87.422 ?   0.147  ns/op
>> -StringFormat.widthStringFormat     avgt   15   250.740 ?  32.639  ns/op
>> -StringFormat.widthStringIntFormat  avgt   15   312.474 ?  16.309  ns/op
>> 
>> +Benchmark                          Mode  Cnt    Score    Error  Units
>> +StringFormat.complexFormat         avgt   15  740.626 ? 66.671  ns/op 
>> (+151.45)
>> +StringFormat.int02Format           avgt   15  131.049 ?  0.432  ns/op 
>> (+138.46)
>> +StringFormat.intFormat             avgt   15   67.229 ?  4.155  ns/op 
>> (+25.59)
>> +StringFormat.longFormat            avgt   15   66.444 ?  0.614  ns/op 
>> (+31.44)
>> +StringFormat.stringFormat          avgt   15   62.619 ?  4.652  ns/op 
>> (+2.19)
>> +StringFormat.stringIntFormat       avgt   15   89.606 ? 13.966  ns/op 
>> (-2.44)
>> +StringFormat.widthStringFormat     avgt   15   52.462 ? 15.649  ns/op 
>> (+377.95)
>> +StringFormat.widthStringIntFormat  avgt   15  101.814 ?  3.147  ns/op 
>> (+206.91)
>
> You might consider this alternative, which IMO is simpler and more readable.
> 
> 
>         int parse() {
>             // %[argument_index$][flags][width][.precision][t]conversion
>             // %(\d+$)?([-#+ 0,(<]*)?(\d+)?(.\d+)?([tT])?([a-zA-Z%])
>             parseArgument();
>             parseFlag();
>             parseWidth();
>             int precisionSize = parsePrecision();
>             if (precisionSize < 0) {
>                 return 0;
>             }
> 
>             // ([tT])?([a-zA-Z%])
>             char t = '\0', conversion = '\0';
>             if ((c == 't' || c == 'T') && off + 1 < max) {
>                 char c1 = s.charAt(off + 1);
>                 if (isConversion(c1)) {
>                     t = c;
>                     conversion = c1;
>                     off += 2;
>                 }
>             }
>             if (conversion == '\0' && isConversion(c)) {
>                 conversion = c;
>                 ++off;
>             }
> 
>             if (argSize + flagSize + widthSize + precisionSize + t + 
> conversion != 0) {
>                 if (al != null) {
>                     FormatSpecifier formatSpecifier
>                             = new FormatSpecifier(s, start, argSize, 
> flagSize, widthSize, precisionSize, t, conversion);
>                     al.add(formatSpecifier);
>                 }
>                 return off - start;
>             }
>             return 0;
>         }
> 
>         private void parseArgument() {
>             // (\d+$)?
>             int i = off;
>             for (; i < max && isDigit(c = s.charAt(i)); ++i);  // empty body
>             if (i == max || c != '$') {
>                 c = first;
>                 return;
>             }
>             ++i;  // skip '$'
>             if (i < max) {
>                 c = s.charAt(i);
>             }
>             argSize = i - off;
>             off = i;
>         }
> 
>         private void parseFlag() {
>             // ([-#+ 0,(<]*)?
>             int i = off;
>             for (; i < max && Flags.isFlag(c = s.charAt(i)); ++i);  // empty 
> body
>             flagSize = i - off;
>             off = i;
>         }
> 
>         private void parseWidth() {
>             // (\d+)?
>             int i = off;
>             for (; i < max && isDigit(c = s.charAt(i)); ++i);  // empty body
>             widthSize = i - off;
>             off = i;
>         }
> 
>         private int parsePrecision() {
>             // (.\d+)?
>             if (c != '.') {
>                 return 0;
>             }
>             int i = off + 1;
>             for (; i < max && isDigit(c = s.charAt(i)); ++i);  // empty bod...

@rgiulietti @cl4es Sorry, I plan to make a change, Now there is part of the 
parser code in the constructor of FormatSpecifier. This is not clear. I plan to 
move the parser part of the constructor of FormatSpecifier into 
FormatSpecifierParser. This will be clearer and the performance will be faster.

* now

        FormatSpecifier(
                String s,
                int i,
                int argSize,
                int flagSize,
                int widthSize,
                int precisionSize,
                char t,
                char conversion
        ) {
            int argEnd = i + argSize;
            int flagEnd = argEnd + flagSize;
            int widthEnd = flagEnd + widthSize;
            int precesionEnd = widthEnd + precisionSize;

            if (argSize > 0) {
                index(s, i, argEnd);
            }
            if (flagSize > 0) {
                flags(s, argEnd, flagEnd);
            }
            if (widthSize > 0) {
                width(s, flagEnd, widthEnd);
            }
            if (precisionSize > 0) {
                precision(s, widthEnd, precesionEnd);
            }
            if (t != '\0') {
                dt = true;
                if (t == 'T') {
                    flags = Flags.add(flags, Flags.UPPERCASE);
                }
            }
            conversion(conversion);
            check();
        }


* plan to:

        FormatSpecifier(int index, int flags, int width, int precision, char t, 
char conversion) {
            if (index > 0) {
                this.index = index;
            }
            if (flags > 0) {
                this.flags = flags;
                if (Flags.contains(flags, Flags.PREVIOUS))
                    this.index = -1;
            }
            if (width > 0) {
                this.width = width;
            }
            this.precision = precision;
            if (t != '\0') {
                dt = true;
                if (t == 'T') {
                    this.flags = Flags.add(flags, Flags.UPPERCASE);
                }
            }
            conversion(conversion);
            check();
        }


FormatSpecifier will not include the functions of parser, and the functions of 
parser are implemented in FormatSpecifierParser.

> Meaningful external reviews take a _lot_ of engineering time on such a 
> popular platform as the JDK.
> They make sense only on somehow stable code, otherwise they are a waste of 
> human resources.
> 
> So sure, take your time to stabilize your code, make your tests, but please 
> refrain from keep on changing too much once you publish a PR. If reviewers 
> have to face continuous changes, they might become uninterested in reviewing.

@rgiulietti I have no plans to make changes, Can you help me continue the 
review? Thank you!

@rgiulietti can you help me continue to review this PR?

-------------

PR Comment: https://git.openjdk.org/jdk/pull/15776#issuecomment-1739269749
PR Comment: https://git.openjdk.org/jdk/pull/15776#issuecomment-1747854315
PR Comment: https://git.openjdk.org/jdk/pull/15776#issuecomment-1764464777

Reply via email to