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

Performance bug in Java Runtime (maybe in HotSpot/JIT)

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 1.4.0
    • 1.3.0
    • hotspot
    • 1.4
    • sparc
    • solaris_2.6



      Name: yyT116575 Date: 01/29/2001


      java version "1.3.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-RC)
      Java HotSpot(TM) Client VM (build 1.3.0-RC, mixed mode)

      Problem observed on
      * JDK 1.3RC, on Solaris 2.6
      * JDK 1.3 Release, on Redhat Linux 6.2, kernel 2.2.16

      In some circumstances, a loop which
      * performs a test and then
      * executes an empty function
      will run slower than a loop which
      * performs a test and then
      * executes a function which performs the same test

      This problem was first observed attempting to perform a benchmark using
      variations of the LinPack benchmark. The following Java source, when compiled,
      demonstrates this issue. In the program output,
      "Orig" Is the loop which simply calls the empty function;
      "Mod" Is the loop which performs the test, then calls a function which performs
      the same test; and
      "Opt" Is the loop which performs the test, then calls an empty function.

      We observed that "Mod" is faster than "Opt", according to our timer, even though
      "Opt" executes less code. This behavior is repeatable. We tried varying the
      parameters and the order of execution, with no change.

      While this doesn't affect the usability of the Java Runtime, we feel it reflects
      a bug in the runtime system or JIT compiler that ought to be addressed.

      --- Begin Code:
      import java.io.*;

      class MethodTest {

        public static void doSomething() {
          flag = false;
          throw new Error();
        }
          
        public static void main(String[] args) throws Exception {
          flag = false;
          MethodTest m = new MethodTest();

          Thread.sleep(2000);
          System.out.println("Opt");
          m.doopt();

          Thread.sleep(2000);
          System.out.println("Mod");
          m.domod();

          Thread.sleep(2000);
          System.out.println("Orig");
          m.do0();

          Thread.sleep(2000);
          System.out.println("Mod");
          m.domod();

          Thread.sleep(2000);
          System.out.println("Opt");
          m.doopt();

          Thread.sleep(2000);
          System.out.println("Orig");
          m.do0();
        }

        Timer sametimer;
        Timer othertimer;
        MethodTest mt;
        public static volatile boolean flag = false;
        static final int METHOD_CALLS = 1000000;

        public void do0() {
          int i;

          sametimer = new Timer();

          sametimer.mark();

          for(i = 0; i < METHOD_CALLS; i++) {
            empty0();
          }

          sametimer.record();
          sametimer.report();
        }

        public void domod() {
          int i;

          if( flag )
            doSomething();
          sametimer = new Timer();

          sametimer.mark();

          for(i = 0; i < METHOD_CALLS; i++) {
            if( flag )
              doSomething();
            empty1();
          }

          sametimer.record();
          sametimer.report();
        }

        public void doopt() {
          int i;

          if( flag )
            doSomething();
          sametimer = new Timer();

          sametimer.mark();

          for(i = 0; i < METHOD_CALLS; i++) {
            if( flag )
              doSomething();
            empty0();
          }

          sametimer.record();
          sametimer.report();
        }

        public void empty0() { }

        public void empty1() {
          if( flag )
            doSomething();
        }
      }

      class Timer {
        private long base_time;
        private long elapsed_time;

        private static final long UNIT = 1000;

        public Timer() {
          clear();
        }

        public void mark() {
          base_time = System.currentTimeMillis();
        }

        public void clear() {
          elapsed_time = 0;
        }

        public void record() {
          elapsed_time += (System.currentTimeMillis() - base_time);
        }

        public float elapsed() {
          return ((float) elapsed_time) / UNIT;
        }

        public void report(PrintStream pstream) {
          float elapsed_seconds = elapsed();
          pstream.println("Time " + elapsed_seconds + " sec");
        }
        public void report() {
          report(System.out);
        }

      }
      --- End Code. ---
      (Review ID: 115926)
      ======================================================================

            duke J. Duke
            yyoungsunw Yung-ching Young (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: