-
Bug
-
Resolution: Fixed
-
P4
-
6
-
mustang
-
x86
-
linux
Name: jl125535 Date: 07/13/2004
FULL PRODUCT VERSION :
java version "1.5.0-beta2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta2-b51)
Java HotSpot(TM) Client VM (build 1.5.0-beta2-b51, mixed mode, sharing)
EXTRA RELEVANT SYSTEM CONFIGURATION :
not relevant
A DESCRIPTION OF THE PROBLEM :
Method getBigDecimal() in class java.text.DigitList can be optimized. Since Tiger, BigDecimal has constructors that accept char[] arguments, and the new method scaleByPowerOfTen() method.
Instead of
<code>
StringBuffer temp = new StringBuffer(count + 12);
temp.append('.');
temp.append(digits, 0, count);
temp.append('E');
temp.append(decimalAt);
return new BigDecimal(temp.toString());
</code>
use
<code>
return new BigDecimal(digits, 0, count).scaleByPowerOfTen(decimalAt - count);
</code>
As a result, DecimalFormat will take about 60% time compared to the current implementation.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the test case. The output will show how long parsing takes. Note that the creation of the BigDecimal the old way takes about 85% of the processing time.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Parsing 12345 for 1000000 times took 1250ms.
Using char[] constructor for 1000000 times took 818ms.
Using StringBuffer for 1000000 times took 1760ms.
ACTUAL -
Parsing 12345 for 1000000 times took 2108ms.
Using char[] constructor for 1000000 times took 818ms.
Using StringBuffer for 1000000 times took 1760ms.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.*;
import java.text.DecimalFormat;
import java.math.BigDecimal;
public class Test {
public static void main(String[] args) {
// TODO code application logic here
String value = "12345";
char[] digits = value.toCharArray();
int decimalAt = 5;
int count = digits.length;
int loopCount = 1000000;
DecimalFormat fmt = new DecimalFormat();
fmt.setParseBigDecimal(true);
try {
BigDecimal d = (BigDecimal) fmt.parse(value);
long startTime, endTime;
/** The normal usage */
startTime = System.currentTimeMillis();
for (int i = 0; i < loopCount; ++i ) {
d = (BigDecimal) fmt.parse(value);
}
endTime = System.currentTimeMillis();
System.out.println("Parsing " + value + " for " + loopCount
+ " times took " + (endTime - startTime) + "ms.");
/** The fast way */
startTime = System.currentTimeMillis();
for (int i = 0; i < loopCount; ++i ) {
d = new BigDecimal(digits, 0, count)
.scaleByPowerOfTen(decimalAt - count);
}
endTime = System.currentTimeMillis();
System.out.println("Using char[] constructor for " + loopCount
+ " times took " + (endTime - startTime) + "ms.");
/** The slow way */
startTime = System.currentTimeMillis();
for (int i = 0; i < loopCount; ++i ) {
StringBuffer temp = new StringBuffer(count + 12);
temp.append('.');
temp.append(digits, 0, count);
temp.append('E');
temp.append(decimalAt);
d = new BigDecimal(temp.toString());
}
endTime = System.currentTimeMillis();
System.out.println("Using StringBuffer for " + loopCount
+ " times took " + (endTime - startTime) + "ms.");
} catch (java.text.ParseException e) {
e.printStackTrace();
}
}
}
---------- END SOURCE ----------
(Incident Review ID: 285234)
======================================================================
###@###.### 10/4/04 03:45 GMT
FULL PRODUCT VERSION :
java version "1.5.0-beta2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta2-b51)
Java HotSpot(TM) Client VM (build 1.5.0-beta2-b51, mixed mode, sharing)
EXTRA RELEVANT SYSTEM CONFIGURATION :
not relevant
A DESCRIPTION OF THE PROBLEM :
Method getBigDecimal() in class java.text.DigitList can be optimized. Since Tiger, BigDecimal has constructors that accept char[] arguments, and the new method scaleByPowerOfTen() method.
Instead of
<code>
StringBuffer temp = new StringBuffer(count + 12);
temp.append('.');
temp.append(digits, 0, count);
temp.append('E');
temp.append(decimalAt);
return new BigDecimal(temp.toString());
</code>
use
<code>
return new BigDecimal(digits, 0, count).scaleByPowerOfTen(decimalAt - count);
</code>
As a result, DecimalFormat will take about 60% time compared to the current implementation.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the test case. The output will show how long parsing takes. Note that the creation of the BigDecimal the old way takes about 85% of the processing time.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Parsing 12345 for 1000000 times took 1250ms.
Using char[] constructor for 1000000 times took 818ms.
Using StringBuffer for 1000000 times took 1760ms.
ACTUAL -
Parsing 12345 for 1000000 times took 2108ms.
Using char[] constructor for 1000000 times took 818ms.
Using StringBuffer for 1000000 times took 1760ms.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.*;
import java.text.DecimalFormat;
import java.math.BigDecimal;
public class Test {
public static void main(String[] args) {
// TODO code application logic here
String value = "12345";
char[] digits = value.toCharArray();
int decimalAt = 5;
int count = digits.length;
int loopCount = 1000000;
DecimalFormat fmt = new DecimalFormat();
fmt.setParseBigDecimal(true);
try {
BigDecimal d = (BigDecimal) fmt.parse(value);
long startTime, endTime;
/** The normal usage */
startTime = System.currentTimeMillis();
for (int i = 0; i < loopCount; ++i ) {
d = (BigDecimal) fmt.parse(value);
}
endTime = System.currentTimeMillis();
System.out.println("Parsing " + value + " for " + loopCount
+ " times took " + (endTime - startTime) + "ms.");
/** The fast way */
startTime = System.currentTimeMillis();
for (int i = 0; i < loopCount; ++i ) {
d = new BigDecimal(digits, 0, count)
.scaleByPowerOfTen(decimalAt - count);
}
endTime = System.currentTimeMillis();
System.out.println("Using char[] constructor for " + loopCount
+ " times took " + (endTime - startTime) + "ms.");
/** The slow way */
startTime = System.currentTimeMillis();
for (int i = 0; i < loopCount; ++i ) {
StringBuffer temp = new StringBuffer(count + 12);
temp.append('.');
temp.append(digits, 0, count);
temp.append('E');
temp.append(decimalAt);
d = new BigDecimal(temp.toString());
}
endTime = System.currentTimeMillis();
System.out.println("Using StringBuffer for " + loopCount
+ " times took " + (endTime - startTime) + "ms.");
} catch (java.text.ParseException e) {
e.printStackTrace();
}
}
}
---------- END SOURCE ----------
(Incident Review ID: 285234)
======================================================================
###@###.### 10/4/04 03:45 GMT