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;

}

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to