Re: RFR: 8327791: Optimization for new BigDecimal(String) [v18]
On Sat, 27 Apr 2024 10:48:38 GMT, Shaojin Wen wrote: >> Shaojin Wen has updated the pull request with a new target base due to a >> merge or a rebase. The incremental webrev excludes the unrelated changes >> brought in by the merge/rebase. The pull request contains 22 additional >> commits since the last revision: >> >> - Merge remote-tracking branch 'upstream/master' into optim_dec_new >> - Merge remote-tracking branch 'upstream/master' into optim_dec_new >> - use while instead for >> - Update src/java.base/share/classes/java/math/BigDecimal.java >> >>Co-authored-by: Claes Redestad >> - bug fix for CharArraySequence#charAt >> - bug fix for CharArraySequence >> - fix benchmark >> - one CharArraySequence >> - restore comment >> - easier to compare >> - ... and 12 more: https://git.openjdk.org/jdk/compare/47953a00...bb620ba3 > > In money-related scenarios, such as product prices, etc., BigDecimal needs to > be used instead of float/double. I focus on optimizing the performance of > BigDecimal's construction and toString scenarios. > > Constructing BigDecimal usually includes two scenarios: > * new BigDecimal(char[], int, int), Many libraries, such as mysql > drveri/fastjson/jackson and other commonly used libraries use this function > to construct BigDecimal > * new BigDecimal(String), There are also many scenarios, such as data > integration scenarios, scenarios where json is read from the message queue > and then converted into target database row records, often using new > BigDecimal(String) > > I did a performance comparison test on Mac Book M1 Pro. The compared branches > are: > * [baseline](https://github.com/wenshao/jdk/tree/upstream_master_0312) > https://github.com/wenshao/jdk/tree/upstream_master_0312 > * bb620ba [Full](https://webrevs.openjdk.org/?repo=jdk&pr=18177&range=17) - > [Incremental](https://webrevs.openjdk.org/?repo=jdk&pr=18177&range=16-17) > ([bb620ba3](https://git.openjdk.org/jdk/pull/18177/files/bb620ba39a6f1ce17ff273bac54ebb709beb1667)) > > > # 1. new BigDecimal(String) benchmark > Execute the following commands respectively > > make test TEST="micro:java.math.BigDecimals.testConstructorWithHugeString" > make test TEST="micro:java.math.BigDecimals.testConstructorWithLargeString" > make test TEST="micro:java.math.BigDecimals.testConstructorWithSmallString" > make test TEST="micro:java.math.BigDecimals.testConstructorWithString" > > > ## benchmark result > > -Benchmark Mode CntScore Error > Units #baseline > -BigDecimals.testConstructorWithHugeString avgt 15 112.994 ? 2.342 > ns/op > -BigDecimals.testConstructorWithLargeString avgt 15 114.016 ? 2.529 > ns/op > -BigDecimals.testConstructorWithSmallString avgt 15 19.526 ? 0.078 > ns/op > -BigDecimals.testConstructorWithString avgt 15 68.058 ? 0.836 > ns/op > > +Benchmark Mode CntScoreError > Units #bb620ba > +BigDecimals.testConstructorWithHugeString avgt 15 96.838 ? 8.743 > ns/op +16.68% > +BigDecimals.testConstructorWithLargeString avgt 15 20.904 ? 0.112 > ns/op +445.42% > +BigDecimals.testConstructorWithSmallString avgt 15 16.083 ? 0.042 > ns/op +21.40% > +BigDecimals.testConstructorWithString avgt 15 35.912 ? 0.350 > ns/op +85.91% > > > It can be seen that there is a significant performance improvement in the new > BigDecimal(Str... @wenshao I think @jddarcy means to share performance improvement in client applications, like in fastjson reading of bigdecimal from JSON, by "interesting workload the change improves". - PR Comment: https://git.openjdk.org/jdk/pull/18177#issuecomment-2080520496
Re: RFR: 8327791: Optimization for new BigDecimal(String) [v18]
On Fri, 26 Apr 2024 05:48:03 GMT, Shaojin Wen wrote: >> The current BigDecimal(String) constructor calls String#toCharArray, which >> has a memory allocation. >> >> >> public BigDecimal(String val) { >> this(val.toCharArray(), 0, val.length()); // allocate char[] >> } >> >> >> When the length is greater than 18, create a char[] >> >> >> boolean isCompact = (len <= MAX_COMPACT_DIGITS); // 18 >> if (!isCompact) { >> // ... >> } else { >> char[] coeff = new char[len]; // allocate char[] >> // ... >> } >> >> >> This PR eliminates the two memory allocations mentioned above, resulting in >> an approximate 60% increase in performance.. > > Shaojin Wen has updated the pull request with a new target base due to a > merge or a rebase. The incremental webrev excludes the unrelated changes > brought in by the merge/rebase. The pull request contains 22 additional > commits since the last revision: > > - Merge remote-tracking branch 'upstream/master' into optim_dec_new > - Merge remote-tracking branch 'upstream/master' into optim_dec_new > - use while instead for > - Update src/java.base/share/classes/java/math/BigDecimal.java > >Co-authored-by: Claes Redestad > - bug fix for CharArraySequence#charAt > - bug fix for CharArraySequence > - fix benchmark > - one CharArraySequence > - restore comment > - easier to compare > - ... and 12 more: https://git.openjdk.org/jdk/compare/26169c54...bb620ba3 In money-related scenarios, such as product prices, etc., BigDecimal needs to be used instead of float/double. I focus on optimizing the performance of BigDecimal's construction and toString scenarios. Constructing BigDecimal usually includes two scenarios: * new BigDecimal(char[], int, int), Many libraries, such as mysql drveri/fastjson/jackson and other commonly used libraries use this function to construct BigDecimal * new BigDecimal(String), There are also many scenarios, such as data integration scenarios, scenarios where json is read from the message queue and then converted into target database row records, often using new BigDecimal(String) I did a performance comparison test on Mac Book M1 Pro. The compared branches are: * [baseline](https://github.com/wenshao/jdk/tree/upstream_master_0312) https://github.com/wenshao/jdk/tree/upstream_master_0312 * bb620ba [Full](https://webrevs.openjdk.org/?repo=jdk&pr=18177&range=17) - [Incremental](https://webrevs.openjdk.org/?repo=jdk&pr=18177&range=16-17) ([bb620ba3](https://git.openjdk.org/jdk/pull/18177/files/bb620ba39a6f1ce17ff273bac54ebb709beb1667)) # 1. new BigDecimal(String) benchmark Execute the following commands respectively make test TEST="micro:java.math.BigDecimals.testConstructorWithHugeString" make test TEST="micro:java.math.BigDecimals.testConstructorWithLargeString" make test TEST="micro:java.math.BigDecimals.testConstructorWithSmallString" make test TEST="micro:java.math.BigDecimals.testConstructorWithString" ## benchmark result -Benchmark Mode CntScore Error Units #baseline -BigDecimals.testConstructorWithHugeString avgt 15 112.994 ? 2.342 ns/op -BigDecimals.testConstructorWithLargeString avgt 15 114.016 ? 2.529 ns/op -BigDecimals.testConstructorWithSmallString avgt 15 19.526 ? 0.078 ns/op -BigDecimals.testConstructorWithString avgt 15 68.058 ? 0.836 ns/op +Benchmark Mode CntScoreError Units #bb620ba +BigDecimals.testConstructorWithHugeString avgt 15 96.838 ? 8.743 ns/op +16.68% +BigDecimals.testConstructorWithLargeString avgt 15 20.904 ? 0.112 ns/op +445.42% +BigDecimals.testConstructorWithSmallString avgt 15 16.083 ? 0.042 ns/op +21.40% +BigDecimals.testConstructorWithString avgt 15 35.912 ? 0.350 ns/op +85.91% It can be seen that there is a significant performance improvement in the new BigDecimal(String) scenario. | case | | |-|-| |BigDecimals.testConstructorWithHugeString |16.68% | |BigDecimals.testConstructorWithLargeString |445.42% | |BigDecimals.testConstructorWithSmallString |21.40% | |BigDecimals.testConstructorWithString |85.91% | # 2. new BigDecima(char[],int,int) benchmark Execute the following commands respectively make test TEST="micro:java.math.BigDecimals.testConstructorWithHugeCharArray" make test TEST="micro:java.math.BigDecimals.testConstructorWithLargeCharArray" make test TEST="micro:java.math.BigDecimals.testConstructorWithSmallCharArray" make test TEST="micro:java.math.BigDecimals.testConstructorWithCharArray" ## benchmark result -Benchmark Mode CntScore Error Units #baseline -BigDecimals.testConstructorWithHugeCharArray avgt 15 94.554 ? 4.262 ns/op -BigDecimals.testConstructorWithLargeCharArray avgt 15 94.669 ? 3.065 ns/op -BigDecimals.testConstructorWithSmallCharArray avgt 15 16.457 ? 0.081 ns/op -BigDeci
Re: RFR: 8327791: Optimization for new BigDecimal(String) [v18]
> The current BigDecimal(String) constructor calls String#toCharArray, which > has a memory allocation. > > > public BigDecimal(String val) { > this(val.toCharArray(), 0, val.length()); // allocate char[] > } > > > When the length is greater than 18, create a char[] > > > boolean isCompact = (len <= MAX_COMPACT_DIGITS); // 18 > if (!isCompact) { > // ... > } else { > char[] coeff = new char[len]; // allocate char[] > // ... > } > > > This PR eliminates the two memory allocations mentioned above, resulting in > an approximate 60% increase in performance.. Shaojin Wen has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 22 additional commits since the last revision: - Merge remote-tracking branch 'upstream/master' into optim_dec_new - Merge remote-tracking branch 'upstream/master' into optim_dec_new - use while instead for - Update src/java.base/share/classes/java/math/BigDecimal.java Co-authored-by: Claes Redestad - bug fix for CharArraySequence#charAt - bug fix for CharArraySequence - fix benchmark - one CharArraySequence - restore comment - easier to compare - ... and 12 more: https://git.openjdk.org/jdk/compare/1701be36...bb620ba3 - Changes: - all: https://git.openjdk.org/jdk/pull/18177/files - new: https://git.openjdk.org/jdk/pull/18177/files/e516b580..bb620ba3 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=18177&range=17 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=18177&range=16-17 Stats: 6763 lines in 129 files changed: 5031 ins; 1483 del; 249 mod Patch: https://git.openjdk.org/jdk/pull/18177.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/18177/head:pull/18177 PR: https://git.openjdk.org/jdk/pull/18177