Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4685588

Random number generator generating bad sequences

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P1 P1
    • 1.4.1
    • 1.4.1
    • hotspot
    • beta
    • sparc
    • solaris_8

      Somwhere between build 8 and build 11, changes were made to the random number generator and the driver for ECperf is no longer generating a random sequence of requests. Here's a distillation of how the ECperf driver uses the random number generator:

      import java.util.*;

      public class TestRand extends Thread {

          private static String alpha = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
          private Random r;
          public int[] buckets;
          int nLoops;

          TestRand(int nLoops) {
              r = new Random();
              buckets = new int[4];
              buckets[0] = buckets[1] = buckets[2] = buckets[3] = 0;
              this.nLoops = nLoops;
          }

          public int random(int x, int y) {
              int n = r.nextInt();
              while (n == Integer.MIN_VALUE)
                  n = r.nextInt();
              int ret = ( x + (Math.abs(n) % (y - x + 1)));
              return ret;
          }

          public double drandom(double x, double y) {
              return ( x + (r.nextDouble()* (y - x)));
          }

          public String make_a_string(int x, int y) {
              int len, i;
              String str = "";
              len = random(x, y);
              for (i = 0; i < len; i++) {
                  int j = random(0, 61);
                  str = str + alpha.substring(j, j + 1);
              }
              return str;
          }

          public int NURand(int A, int x, int y) {
              return ((random(0, A) | random(x, y)) % (y - x + 1)) + x;
          }

          public void run() {
              for (int i = 0; i < nLoops; i++) {
                  int x = random(1, 100);
                  if (x <= 10) {
                      buckets[0]++;
                  }
                  else if (x <= 30) {
                      buckets[1]++;
                  }
                  else if (x <= 50) {
                      buckets[2]++;
                  }
                  else if (x <= 100) {
                      buckets[3]++;
                      make_a_string(10,20);
                      make_a_string(10,20);
                      make_a_string(10,20);
                      make_a_string(10,20);
                      make_a_string(10,20);
                      random(1, 100);
                  }
                  drandom(0.0, 1.0);
              }
          }

          public static void main(String[] args) throws Exception {
              int nLoops = Integer.parseInt(args[0]);
              int nThreads = Integer.parseInt(args[1]);
              int[] agg = new int[4];

              TestRand[] tr = new TestRand[nThreads];
              agg[0] = agg[1] = agg[2] = agg[3] = 0;

              for (int i = 0; i < nThreads; i++) {
                  tr[i] = new TestRand(nLoops);
                  tr[i].start();
              }

              for (int i = 0; i < nThreads; i++) {
                  tr[i].join();
                  agg[0] += tr[i].buckets[0];
                  agg[1] += tr[i].buckets[1];
                  agg[2] += tr[i].buckets[2];
                  agg[3] += tr[i].buckets[3];
              }

              System.out.println("Distribution:\n");
              System.out.println("\tBucket 1 (Expected 10%): " + ((float) agg[0]/(nLoops * nThreads)));
              System.out.println("\tBucket 2 (Expected 20%): " + ((float) agg[1]/(nLoops * nThreads)));
              System.out.println("\tBucket 3 (Expected 20%): " + ((float) agg[2]/(nLoops * nThreads)));
              System.out.println("\tBucket 4 (Expected 50%): " + ((float) agg[3]/(nLoops * nThreads)));
          }
      }

      Here's the output of this program under Merlin:
      %java -version
      java version "1.4.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
      %java -server -Xmx3500m -Xms3500m TestRand
      Distribution:
       
              Bucket 1 (Expected 10%): 0.0997714
              Bucket 2 (Expected 20%): 0.2004684
              Bucket 3 (Expected 20%): 0.1997232
              Bucket 4 (Expected 50%): 0.500037


      Here's the output with Hopper build 11:
      %java -version
      java version "1.4.1-beta"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-beta-b11)
      %java -server -Xmx3500m -Xms3500m TestRand

      Distribution:
       
              Bucket 1 (Expected 10%): 0.1186286
              Bucket 2 (Expected 20%): 0.2264459
              Bucket 3 (Expected 20%): 0.2329252
              Bucket 4 (Expected 50%): 0.4220003

      On an actual ECperf run (which is much longer and also more complex in its usage of the Random class), this observed distribution is .47, .08, .38, .06 [yes, the 10% bucket is getting 47% of the distribution].


      ====================================================================================

      Although not noted above, this also causes ECPerf to fail (not just produce a
      bad distribution)

      JBB2000 also fails with Validation errors due to this bug. I've already confirmed
      that a build from Steve containing the fix for the above test case also fixes
      this problem. Here's the problem (very consistent):

      ...
      JVM Check OK
      Constructing the company now Hang....on

      Loading Warehouse 1...


      VALIDATION ERROR: incorrect output for NewOrderTransaction
          Line 3 should be: |Customer: 17 Name: BAROUGHTANTI Credit: GC %Disc: 43.11|
          Line 3 is: |Customer: 10 Name: BARBAREING Credit: GC %Disc: 12.70|
      VALIDATION ERROR: incorrect output for NewOrderTransaction
          Line 4 should be: |Order Number: 31 Number of Lines: 15 W_tax: 10.30 D_tax: 6.62|
          Line 4 is: |Order Number: 31 Number of Lines: 8 W_tax: 3.91 D_tax: 2.75|
      VALIDATION ERROR: incorrect output for NewOrderTransaction
          Line 7 should be: | 1 12117 rk9rIQP9q52FiN4FWuihzNT 5 59 G $61.73 $308.65|
          Line 7 is: | 1 5838 kLI6JutC1hODssxvj 5 44 G $46.46 $232.30|
      VALIDATION ERROR: incorrect output for NewOrderTransaction
          Line 8 should be: | 1 19072 0VOgv21kW1ZS3pv1IzirxrmH 5 79 G $26.62 $133.10|
          Line 8 is: | 1 5838 kLI6JutC1hODssxvj 5 39 G $46.46 $232.30|
      VALIDATION ERROR: incorrect output for NewOrderTransaction
          Line 9 should be: | 1 4260 clRd7h9zm9eGwqtvKblk1q 5 53 G $85.08 $425.40|
          Line 9 is: | 1 5838 kLI6JutC1hODssxvj 5 34 G $46.46 $232.30|
      VALIDATION ERROR: incorrect output for NewOrderTransaction
          Line 10 should be: | 1 5772 b96nAb1I7qPaOA 5 73 G $50.24 $251.20

      .... many others


      ###@###.### 2002-05-17

      ====================================================================================

            sdeversunw Steve Dever (Inactive)
            soaks Scott Oaks (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: