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

A big win for concrete class inference

XMLWordPrintable

    • generic
    • generic

      FULL PRODUCT VERSION :
      java version "1.5.0_05"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_05-b05)
      Java HotSpot(TM) Client VM (build 1.5.0_05-b05, mixed mode)

      FULL OPERATING SYSTEM VERSION :
      SunOS s0046mqa 5.7 Generic_106541-15 sun4us sparc FJSV,GPUS

      A DESCRIPTION OF THE PROBLEM :
      Summing up the elements of an int[] array using interfaces
      for both the Iterator and the int wrapper Object takes 10
      times(!) longer than using the concrete classes (on Solaris
      7/SPARC, on Linux/Intel 2.3x, on WindowsNT 2.5x).

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      for a in 0 1 2 3 4 5 6
      do
        java -server SlowInterface 1000000 20 20 $a
      done


      ACTUAL BEHAVIOR :
      Linux on Pentium 4 mobile, 1.6 GHz, -server VM:
      0: 215ms
      1: 1715ms
      2: 983ms
      3: 1004ms
      4: 264ms
      5: 311ms
      6: 160ms

      Windows XP on Pentium 4, 2.4 GHz, 1Gb RAM, -server VM:
      0: 94ms
      1: 609ms
      2: 594ms
      3: 594ms
      4: 188ms
      5: 203ms
      6: 78ms

      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.util.*;

      public class SlowInterface {
          //----------------------------------------------------------------------
          // int wrapper
          //----------------------------------------------------------------------
          private interface intReadRef {
      int get ();
          }

          private interface intWriteRef {
      void set (int value);
          }

          private interface intRef extends intReadRef, intWriteRef { }

          private static final class MutableInt implements intRef {
      private int value;
      public MutableInt (int value) { this.value = value; }
      public MutableInt () { }
      public int get () { return value; }
      public void set (int value) { this.value = value; }
          }

          //----------------------------------------------------------------------
          // int[] iterators
          //----------------------------------------------------------------------
          private static abstract class IntArrayIterator implements Iterator {
      protected final int[] a;
      protected final int length;
      protected int i;
      protected int lastI = -1;
      protected IntArrayIterator (int[] a, int i) { this.a = a; this.i = i;
      length = a.length; }
      public IntArrayIterator (int[] a) { this (a, 0); }
      public final boolean hasNext () { return length > i; }
      public final Object next () {
      try {
      return getUnchecked (lastI = i++);
      } catch (ArrayIndexOutOfBoundsException e) {
      throw new NoSuchElementException ("index: " + (lastI = --i)
      + ", length: " + length);
      }
      }
      public final void remove () { throw new UnsupportedOperationException
      (); }
      protected abstract Object getUnchecked (int i);
          }

          private static final class MutableIterator extends IntArrayIterator {
      private final MutableInt result = new MutableInt ();
      public MutableIterator (int[] a) { super (a); }
      protected Object getUnchecked (int i) { result.set (a [i]); return
      result; }
          }

          //----------------------------------------------------------------------
          private static final long run (int alg, int[] a, long expectedSum, int n) {
      long start = System.currentTimeMillis ();
      for (int r = 0; r < n; ++r) {
      long s = 0;

      switch (alg) {
      case 0: {
      for (int i = 0; i < a.length; ++i) {
      s += a [i];
      }
      } break;

      case 1: {
      for (Iterator i = new MutableIterator (a); i.hasNext (); ) {
      s += ((intReadRef)i.next ()).get ();
      }
      } break;

      case 2: {
      for (Iterator i = new MutableIterator (a); i.hasNext (); ) {
      s += ((intRef)i.next ()).get ();
      }
      } break;

      case 3: {
      for (Iterator i = new MutableIterator (a); i.hasNext (); ) {
      s += ((MutableInt)i.next ()).get ();
      }
      } break;

      case 4: {
      for (MutableIterator i = new MutableIterator (a); i.hasNext
      (); ) {
      s += ((intReadRef)i.next ()).get ();
      }
      } break;

      case 5: {
      for (MutableIterator i = new MutableIterator (a); i.hasNext
      (); ) {
      s += ((intRef)i.next ()).get ();
      }
      } break;

      case 6: {
      for (MutableIterator i = new MutableIterator (a); i.hasNext
      (); ) {
      s += ((MutableInt)i.next ()).get ();
      }
      } break;

      }

      if (s != expectedSum) {
      throw new IllegalStateException ("wrong sum (expected: " +
      expectedSum + "; actual: " + s + ")");
      }
      }
      return System.currentTimeMillis () - start;
          }

          public static void main (String[] args) {
      int length = Integer.parseInt (args [0]);
      int warmup = Integer.parseInt (args [1]);
      int measure = Integer.parseInt (args [2]);
      int alg = Integer.parseInt (args [3]);
      int[] a = new int [length];
      long expectedSum = (length / 2L) * (length + 1L);

      // fill
      for (int i = 0; i < length; ++i) {
      a [ i] = i + 1;
      }

      run (alg, a, expectedSum, warmup);
      System.out.println (alg + ": " + run (alg, a, expectedSum, warmup)
      + "ms");
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER WORKAROUND :
      Cast down to the concrete classes (not possible if concrete
      classes are private inner classes).

            jrose John Rose
            jleesunw Jon Lee (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: