Re: RFR: 8333396: Performance regression of DecimalFormat.format [v6]

2024-06-17 Thread Naoto Sato
On Mon, 17 Jun 2024 20:10:18 GMT, Chen Liang  wrote:

>> For StringBuf proxy, is it acceptible for us to introduce a new jdk.internal 
>> public interface (accessible only within java.base module) to expose common 
>> public methods in AbstractStringBuilder? We have public types extending or 
>> implementing non-public-types in the JDK (AbstractStringBuilder, 
>> NamedPackage) so I guess having a new module-specific superinterface would 
>> be fine? Need verification from API experts.
>
>> Hi @liach Do you know any other places within java.base where we would need 
>> the same proxy for StringBuffer?
> 
> Good question! I looked at 
> https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/class-use/StringBuffer.html.
>  I think such a new interface indeed is of limited usefulness, as we don't 
> really have that many non-java.lang APIs closely tied to StringBuffer. 
> Matcher is like one, but it lives mostly fine without the shadowing because 
> it is using `Appendable`. And this has enlightened me.
> 
> In fact, we can use `Appendable` too, as we just need 2 `append` from 
> `Appendable` and `subSequence` (replacing `substring`) and `length` from 
> `CharSequence`. We can declare method like:
> 
>  T format(double number, T toAppendTo,
>  FieldPosition status) {
> 
> This signature accepts both `StringBuilder` and `StringBuffer`; all use sites 
> can be according updated. The only thing need to change is that `substring` 
> should now become `subSequence`, but it's just used in 
> `CharacterIteratorFieldDelegate` so the impact is small.

> > Hi @liach Do you know any other places within java.base where we would need 
> > the same proxy for StringBuffer?
> 
> Good question! I looked at 
> https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/class-use/StringBuffer.html.
>  I think such a new interface indeed is of limited usefulness, as we don't 
> really have that many non-java.lang APIs closely tied to StringBuffer. 
> Matcher is like one, but it lives mostly fine without the shadowing because 
> it is using `Appendable`. And this has enlightened me.
> 
> In fact, we can use `Appendable` too, as we just need 2 `append` from 
> `Appendable` and `subSequence` (replacing `substring`) and `length` from 
> `CharSequence`. We can declare method like:
> 
> ```java
>  T format(double number, T toAppendTo,
>  FieldPosition status) {
> ```
> 
> This signature accepts both `StringBuilder` and `StringBuffer`; all use sites 
> can be according updated. The only thing need to change is that `substring` 
> should now become `subSequence`, but it's just used in 
> `CharacterIteratorFieldDelegate` so the impact is small.

That looks promising! Much cleaner than having dual methods

-

PR Comment: https://git.openjdk.org/jdk/pull/19513#issuecomment-2174509435


Re: RFR: 8333396: Performance regression of DecimalFormat.format [v6]

2024-06-17 Thread Chen Liang
On Mon, 17 Jun 2024 18:47:11 GMT, Chen Liang  wrote:

>> lingjun-cg has updated the pull request incrementally with one additional 
>> commit since the last revision:
>> 
>>   896: Performance regression of DecimalFormat.format
>
> For StringBuf proxy, is it acceptible for us to introduce a new jdk.internal 
> public interface (accessible only within java.base module) to expose common 
> public methods in AbstractStringBuilder? We have public types extending or 
> implementing non-public-types in the JDK (AbstractStringBuilder, 
> NamedPackage) so I guess having a new module-specific superinterface would be 
> fine? Need verification from API experts.

> Hi @liach Do you know any other places within java.base where we would need 
> the same proxy for StringBuffer?

Good question! I looked at 
https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/class-use/StringBuffer.html.
 I think such a new interface indeed is of limited usefulness, as we don't 
really have that many non-java.lang APIs closely tied to StringBuffer. Matcher 
is like one, but it lives mostly fine without the shadowing because it is using 
`Appendable`. And this has enlightened me.

In fact, we can use `Appendable` too, as we just need 2 `append` from 
`Appendable` and `subSequence` (replacing `substring`) and `length` from 
`CharSequence`. We can declare method like:

 T format(double number, T toAppendTo,
 FieldPosition status) {

This signature accepts both `StringBuilder` and `StringBuffer`; all use sites 
can be according updated. The only thing need to change is that `substring` 
should now become `subSequence`, but it's just used in 
`CharacterIteratorFieldDelegate` so the impact is small.

-

PR Comment: https://git.openjdk.org/jdk/pull/19513#issuecomment-2174336411


Re: RFR: 8333396: Performance regression of DecimalFormat.format [v6]

2024-06-17 Thread Naoto Sato
On Mon, 17 Jun 2024 18:47:11 GMT, Chen Liang  wrote:

>> lingjun-cg has updated the pull request incrementally with one additional 
>> commit since the last revision:
>> 
>>   896: Performance regression of DecimalFormat.format
>
> For StringBuf proxy, is it acceptible for us to introduce a new jdk.internal 
> public interface (accessible only within java.base module) to expose common 
> public methods in AbstractStringBuilder? We have public types extending or 
> implementing non-public-types in the JDK (AbstractStringBuilder, 
> NamedPackage) so I guess having a new module-specific superinterface would be 
> fine? Need verification from API experts.

Hi @liach 
Do you know any other places within java.base where we would need the same 
proxy for StringBuffer?

-

PR Comment: https://git.openjdk.org/jdk/pull/19513#issuecomment-2174283589


Re: RFR: 8333396: Performance regression of DecimalFormat.format [v6]

2024-06-17 Thread Chen Liang
On Fri, 14 Jun 2024 03:19:48 GMT, lingjun-cg  wrote:

>> ### Performance regression of DecimalFormat.format
>> From the output of perf, we can see the hottest regions contain atomic 
>> instructions.  But when run with JDK 11, there is no such problem. The 
>> reason is the removed biased locking.  
>> The DecimalFormat uses StringBuffer everywhere, and StringBuffer itself 
>> contains many synchronized methods.
>> So I added support for some new methods that accept StringBuilder which is 
>> lock-free.
>> 
>> ### Benchmark testcase
>> 
>> @BenchmarkMode(Mode.AverageTime)
>> @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
>> @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
>> @State(Scope.Thread)
>> @OutputTimeUnit(TimeUnit.NANOSECONDS)
>> public class JmhDecimalFormat {
>> 
>> private DecimalFormat format;
>> 
>> @Setup(Level.Trial)
>> public void setup() {
>> format = new DecimalFormat("#0.0");
>> }
>> 
>> @Benchmark
>> public void testNewAndFormat() throws InterruptedException {
>> new DecimalFormat("#0.0").format(9524234.1236457);
>> }
>> 
>> @Benchmark
>> public void testNewOnly() throws InterruptedException {
>> new DecimalFormat("#0.0");
>> }
>> 
>> @Benchmark
>> public void testFormatOnly() throws InterruptedException {
>> format.format(9524234.1236457);
>> }
>> }
>> 
>> 
>> ### Test result
>>  Current JDK before optimize
>> 
>>  Benchmark Mode  CntScore   Error  Units
>> JmhDecimalFormat.testFormatOnly   avgt   50  642.099 ? 1.253  ns/op
>> JmhDecimalFormat.testNewAndFormat avgt   50  989.307 ? 3.676  ns/op
>> JmhDecimalFormat.testNewOnly  avgt   50  303.381 ? 5.252  ns/op
>> 
>> 
>> 
>>  Current JDK after optimize
>> 
>> Benchmark  Mode  CntScore   Error  Units
>> JmhDecimalFormat.testFormatOnlyavgt   50  351.499 ? 0.761  ns/op
>> JmhDecimalFormat.testNewAndFormat  avgt   50  615.145 ? 2.478  ns/op
>> JmhDecimalFormat.testNewOnly   avgt   50  209.874 ? 9.951  ns/op
>> 
>> 
>> ### JDK 11 
>> 
>> Benchmark  Mode  CntScore   Error  Units
>> JmhDecimalFormat.testFormatOnlyavgt   50  364.214 ? 1.191  ns/op
>> JmhDecimalFormat.testNewAndFormat  avgt   50  658.699 ? 2.311  ns/op
>> JmhDecimalFormat.testNewOnly   avgt   50  248.300 ? 5.158  ns/op
>
> lingjun-cg has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   896: Performance regression of DecimalFormat.format

For StringBuf proxy, is it acceptible for us to introduce a new jdk.internal 
public interface (accessible only within java.base module) to expose common 
public methods in AbstractStringBuilder? We have public types extending or 
implementing non-public-types in the JDK (AbstractStringBuilder, NamedPackage) 
so I guess having a new module-specific superinterface would be fine? Need 
verification from API experts.

-

PR Comment: https://git.openjdk.org/jdk/pull/19513#issuecomment-2174193760


Re: RFR: 8333396: Performance regression of DecimalFormat.format [v6]

2024-06-13 Thread lingjun-cg
> ### Performance regression of DecimalFormat.format
> From the output of perf, we can see the hottest regions contain atomic 
> instructions.  But when run with JDK 11, there is no such problem. The reason 
> is the removed biased locking.  
> The DecimalFormat uses StringBuffer everywhere, and StringBuffer itself 
> contains many synchronized methods.
> So I added support for some new methods that accept StringBuilder which is 
> lock-free.
> 
> ### Benchmark testcase
> 
> @BenchmarkMode(Mode.AverageTime)
> @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
> @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
> @State(Scope.Thread)
> @OutputTimeUnit(TimeUnit.NANOSECONDS)
> public class JmhDecimalFormat {
> 
> private DecimalFormat format;
> 
> @Setup(Level.Trial)
> public void setup() {
> format = new DecimalFormat("#0.0");
> }
> 
> @Benchmark
> public void testNewAndFormat() throws InterruptedException {
> new DecimalFormat("#0.0").format(9524234.1236457);
> }
> 
> @Benchmark
> public void testNewOnly() throws InterruptedException {
> new DecimalFormat("#0.0");
> }
> 
> @Benchmark
> public void testFormatOnly() throws InterruptedException {
> format.format(9524234.1236457);
> }
> }
> 
> 
> ### Test result
>  Current JDK before optimize
> 
>  Benchmark Mode  CntScore   Error  Units
> JmhDecimalFormat.testFormatOnly   avgt   50  642.099 ? 1.253  ns/op
> JmhDecimalFormat.testNewAndFormat avgt   50  989.307 ? 3.676  ns/op
> JmhDecimalFormat.testNewOnly  avgt   50  303.381 ? 5.252  ns/op
> 
> 
> 
>  Current JDK after optimize
> 
> Benchmark  Mode  CntScore   Error  Units
> JmhDecimalFormat.testFormatOnlyavgt   50  351.499 ? 0.761  ns/op
> JmhDecimalFormat.testNewAndFormat  avgt   50  615.145 ? 2.478  ns/op
> JmhDecimalFormat.testNewOnly   avgt   50  209.874 ? 9.951  ns/op
> 
> 
> ### JDK 11 
> 
> Benchmark  Mode  CntScore   Error  Units
> JmhDecimalFormat.testFormatOnlyavgt   50  364.214 ? 1.191  ns/op
> JmhDecimalFormat.testNewAndFormat  avgt   50  658.699 ? 2.311  ns/op
> JmhDecimalFormat.testNewOnly   avgt   50  248.300 ? 5.158  ns/op

lingjun-cg has updated the pull request incrementally with one additional 
commit since the last revision:

  896: Performance regression of DecimalFormat.format

-

Changes:
  - all: https://git.openjdk.org/jdk/pull/19513/files
  - new: https://git.openjdk.org/jdk/pull/19513/files/1ab65e18..d590f132

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jdk&pr=19513&range=05
 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=19513&range=04-05

  Stats: 467 lines in 11 files changed: 222 ins; 188 del; 57 mod
  Patch: https://git.openjdk.org/jdk/pull/19513.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/19513/head:pull/19513

PR: https://git.openjdk.org/jdk/pull/19513