Skip to content

Commit

Permalink
[Runtime] optimize BigDecimal.divide
Browse files Browse the repository at this point in the history
Summary: Use binary search in zero stripping of BigDecimal.divide

Testing: jtreg

Reviewers:

Issue: https://github.com/dragonwell-project/dragonwell11/issues/

CR: https://github.com/dragonwell-project/dragonwell11/pull/
  • Loading branch information
weixlu committed Jul 30, 2024
1 parent 1811fb0 commit d1d8c8f
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/hotspot/share/runtime/arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4115,6 +4115,10 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) {
DumpAppCDSWithKlassId = true;
}

if (UseBigDecimalOpt) {
PropertyList_add(&_system_properties, new SystemProperty("java.math.BigDecimal.opt", "true", true));
}

// Set object alignment values.
set_object_alignment();

Expand Down
3 changes: 3 additions & 0 deletions src/hotspot/share/runtime/globals_ext.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@
product(bool, ReduceNMethodSize, false, \
"Move immutable data of nmethod out of code cache") \
\
product(bool, UseBigDecimalOpt, true, \
"use binary search in zero stripping of BigDecimal") \
\
//add new AJDK specific flags here


Expand Down
45 changes: 45 additions & 0 deletions src/java.base/share/classes/java/math/BigDecimal.java
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,16 @@ protected StringBuilderHelper initialValue() {
*/
private static final BigDecimal ONE_HALF = valueOf(5L, 1);

private static boolean opt;
static {
try {
opt = Boolean.parseBoolean(System.getProperty("java.math.BigDecimal.optimization"));
} catch (SecurityException e) {
// When user define some secure environment, system property here may be inaccessible.
opt = false;
}
}

// Constructors

/**
Expand Down Expand Up @@ -4860,6 +4870,38 @@ private static boolean needIncrement(MutableBigInteger mdivisor, int roundingMod
return commonNeedIncrement(roundingMode, qsign, cmpFracHalf, mq.isOdd());
}

/**
* Remove insignificant trailing zeros from this
* {@code BigInteger} value until the preferred scale is reached or no
* more zeros can be removed. This is a faster version of createAndStripZerosToMatchScale
* using binary search instead of linear search.
*
* @return new {@code BigDecimal} with a scale possibly reduced
* to be closed to the preferred scale.
*/
private static BigDecimal createAndStripZerosToMatchScaleFast(BigInteger intVal, int scale, long preferredScale) {
BigInteger qr[]; // quotient-remainder pair
int scaleStep;
while (intVal.compareMagnitude(BigInteger.TEN) >= 0
&& scale > preferredScale) {
scaleStep = checkScale(intVal, Math.max(((long) scale - preferredScale) / 2, 1l));
if (intVal.getLowestSetBit() >= scaleStep) { // intVal can be divided by pow(10, scaleStep) only if intVal has more trailing zeros than scaleStep
qr = intVal.divideAndRemainder(bigTenToThe(scaleStep));
if (qr[1].signum() == 0) {
intVal = qr[0];
scale = checkScale(intVal, (long) scale - scaleStep); // could Overflow
continue;
}
}
if (scaleStep == 1) {
break;
} else {
preferredScale = scale - scaleStep;
}
}
return valueOf(intVal, scale, 0);
}

/**
* Remove insignificant trailing zeros from this
* {@code BigInteger} value until the preferred scale is reached or no
Expand All @@ -4870,6 +4912,9 @@ private static boolean needIncrement(MutableBigInteger mdivisor, int roundingMod
* to be closed to the preferred scale.
*/
private static BigDecimal createAndStripZerosToMatchScale(BigInteger intVal, int scale, long preferredScale) {
if (opt && preferredScale >= Integer.MIN_VALUE) {
return createAndStripZerosToMatchScaleFast(intVal, scale, preferredScale);
}
BigInteger qr[]; // quotient-remainder pair
while (intVal.compareMagnitude(BigInteger.TEN) >= 0
&& scale > preferredScale) {
Expand Down

0 comments on commit d1d8c8f

Please sign in to comment.