I think this goes against the grain: StringBuilder is a simple builder for 
non-localized unformatted output. For formatted output there’s Formatter, 
String.format and, with JEP 430[1], FMT.”…” to help output string data in more 
advanced, formatted and localized ways. The latter has traditionally lacked a 
bit in raw throughput, and String templates is a deep-cut approach to try and 
improve both the programming model and the performance characteristics.

Let’s compare a few existing APIs (JDK 22 ea, —enable-preview enabled for the 
FMT.”…” micro:


@Benchmark
public String toStringAppendHex8() {
    StringBuilder result = new StringBuilder();
    result.append(Integer.toHexString(2048));
    result.append(Integer.toHexString(31337));
    result.append(Integer.toHexString(0xbeefcace));
    result.append(Integer.toHexString(9000));
    result.append(Integer.toHexString(4711));
    result.append(Integer.toHexString(1337));
    result.append(Integer.toHexString(2100));
    result.append(Integer.toHexString(2600));
    return result.toString();
}

@Benchmark
public String toStringFMTHex8() {
    int h1 = 2048, h2 = 31337, h3 = 0xbeefcace, h4 = 9000, h5 = 4711, h6 = 
1337, h7 = 2100, h8 = 2600;
    return FMT."%x\{h1}%x\{h2}%x\{h3}%x\{h4}%x\{h5}%x\{h6}%x\{h7}%x\{h8}";
}

@Benchmark
public String toStringFormatHex8() {
    StringBuilder result = new StringBuilder();
    Formatter f = new Formatter(result);
    f.format("%x", 2048);
    f.format("%x", 31337);
    f.format("%x", 0xbeefcace);
    f.format("%x", 9000);
    f.format("%x", 4711);
    f.format("%x", 1337);
    f.format("%x", 2100);
    f.format("%x", 2600);
    return result.toString();
}

@Benchmark
public String toStringFormatCombinedHex8() {
    return String.format("%x%x%x%x%x%x%x%x", 2048, 31337, 0xbeefcace, 9000, 
4711, 1337, 2100, 2600);
}


Benchmark                                  Mode  Cnt    Score   Error  Units
StringBuilders.toStringAppendHex8          avgt   15   19,521 ± 0,608  ns/op
StringBuilders.toStringFMTHex8             avgt   15   10,958 ± 0,838  ns/op
StringBuilders.toStringFormatHex8          avgt   15  378,327 ± 9,302  ns/op
StringBuilders.toStringFormatCombinedHex8  avgt   15  235,609 ± 6,315  ns/op

As we can see FMT.”%x…” is already a great deal faster here, while 
String.format and Formatter leave something to be desired.

One thing missing with the FMT approach is a natural way to format into 
pre-existing StringBuilder/Appendable (like the toStringFormatHex8 benchmark 
models). I think adding that would be a way more interesting development than 
to add more formatting methods to StringBuilder.

/Claes

[1] https://openjdk.org/jeps/430

30 sep. 2023 kl. 14:06 skrev 温绍锦(高铁) <shaojin.we...@alibaba-inc.com>:

There are many combinations of `append(Integer.toHexString(i))` and 
`append(Long.toHexString(i))` in the JDK code. I request to add method 
`appendHex(int)` and `appendHex(int)` to StringBuilder and StringBuffer. This 
can reduce duplicate code within the JDK and will also be useful to users.

I submitted a PR ( https://github.com/openjdk/jdk/pull/15998 ), including the 
code and tests for the new method. I also replaced the code that uses the 
append + toHexString combination inside the JDK with appendHex.

Please review and don't hesitate to critique my approach and patch.

Reply via email to