I couldn't sleep last night so I decided to read the Java source. Sending a patch that very evening was a *bad* idea. Sorry about that. The arraycopy method did not improve things at all.
However, the minor changes actually do work. The attachments original.log and patched.log each contain 5 results of Benchmark.java. OpenJDK Runtime Environment (build 1.7.0-internal-pascal_03_jul_2007_21_30-b00) Java flags: "-server -Xnoclassgc" Happy ending after all?
Index: BigInteger.java
===================================================================
--- BigInteger.java (revision 239)
+++ BigInteger.java (working copy)
@@ -1095,20 +1095,24 @@
long sum = 0;
// Add common parts of both numbers
- while(yIndex > 0) {
- sum = (x[--xIndex] & LONG_MASK) +
- (y[--yIndex] & LONG_MASK) + (sum >>> 32);
- result[xIndex] = (int)sum;
+ while (yIndex != 0) {
+ long xl = x[--xIndex] & LONG_MASK;
+ long yl = y[--yIndex] & LONG_MASK;
+ sum = xl + yl + (sum >>> 32);
+ result[xIndex] = (int) sum;
}
// Copy remainder of longer number while carry propagation is required
- boolean carry = (sum >>> 32 != 0);
- while (xIndex > 0 && carry)
- carry = ((result[--xIndex] = x[xIndex] + 1) == 0);
+ boolean carry = (sum >>> 32) != 0;
+ while (carry && --xIndex >= 0) {
+ int flow = x[xIndex] + 1;
+ result[xIndex] = flow;
+ carry = flow == 0;
+ }
// Copy remainder of longer number
- while (xIndex > 0)
- result[--xIndex] = x[xIndex];
+ while (--xIndex >= 0)
+ result[xIndex] = x[xIndex];
// Grow result if necessary
if (carry) {
size averange minimum maximum 32 1536 1463 1967 256 2366 2315 2516 8192 41051 40412 41675 size averange minimum maximum 32 1529 1482 1586 256 2379 2316 2681 8192 41120 40091 42027 size averange minimum maximum 32 1563 1483 1881 256 2372 2331 2455 8192 41004 40295 41716 size averange minimum maximum 32 1530 1469 1589 256 2374 2332 2469 8192 41116 40201 41965 size averange minimum maximum 32 1537 1476 1800 256 2388 2317 2872 8192 41190 40856 41714
size averange minimum maximum 32 1486 1430 1522 256 2273 2235 2320 8192 39374 38999 40453 size averange minimum maximum 32 1499 1447 1605 256 2290 2239 2353 8192 39262 38887 40016 size averange minimum maximum 32 1480 1441 1542 256 2326 2291 2640 8192 41138 39881 41844 size averange minimum maximum 32 1486 1430 1515 256 2287 2228 2436 8192 39299 38989 39865 size averange minimum maximum 32 1475 1415 1524 256 2309 2247 2704 8192 39340 38987 40035
import java.util.Random;
import java.math.BigInteger;
public class Benchmark {
public static void
main(String[] args) {
int i = 30;
long[] small = new long[i];
long[] medium = new long[i];
long[] large = new long[i];
// warming up:
benchAdd(SMALL);
benchAdd(MEDIUM);
benchAdd(LARGE);
benchAdd(SMALL);
benchAdd(MEDIUM);
benchAdd(LARGE);
while (--i >= 0) {
small[i] = benchAdd(SMALL);
medium[i] = benchAdd(MEDIUM);
large[i] = benchAdd(LARGE);
}
System.out.print("size averange minimum maximum\n");
print(small, SMALL);
print(medium, MEDIUM);
print(large, LARGE);
}
private static void
print(long[] result, int size) {
int i = result.length;
long x = result[--i];
long min = x;
long max = x;
long averange = x;
while (--i >= 0) {
x = result[i];
if (x < min) min = x;
if (x > max) max = x;
averange += x;
}
averange /= result.length;
System.out.printf("%4d %8d %7d %7d\n", size, averange, min, max);
}
private static long
benchAdd(int size) {
BigInteger[] a = getData(size);
BigInteger[] b = getData(size);
System.gc();
int i = SAMPLES;
long start = System.nanoTime();
while (--i >= 0)
a[i].add(b[i]);
long end = System.nanoTime();
return (end - start) / 1000;
}
private static BigInteger[]
getData(int size) {
Random random = new Random(99);
int i = SAMPLES;
BigInteger[] data = new BigInteger[i];
while (--i >= 0)
data[i] = new BigInteger(size, random);
return data;
}
private static final int SAMPLES = 10000;
private static final int LARGE = 8192;
private static final int MEDIUM = 256;
private static final int SMALL = 32;
}
signature.asc
Description: This is a digitally signed message part.
