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

Poor performance with multiple threads and object creation

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P3 P3
    • None
    • 1.3.0
    • hotspot
    • gc
    • x86
    • windows_nt



      Name: krC82822 Date: 01/25/2001


      java version "1.3.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
      Java HotSpot(TM) Server VM (build 2.0fcs-E, mixed mode)

      We've been doing some performance comparisons of Sun JVM on Intel PCs and
      Sparcs. One of our tests shows poor scaling of the Sun JVM on PCs cf
      Sparc (and other JVMs on PCs). The problem is related to an increasing
      number of threads (up to 1000 concurrently) and increasing number of
      objects created in each thread. For sparc and non-Sun JVM (e.g. IBM JVM)
      on PC we get reasonable performance. For Sun JVM we get very poor
      and increasing times with number of threads. Here's the raw figures
      from our excel spreadsheet. Column on left is number of threads,
      then time in ms for Ultra 80, Dell 420 PC, and Dell 420 PC with IBM JVM.

      Threads Ultra PC IBM JVM (PC)
      1 3740 15641 26282
      2 3639 26719 14750
      5 4866 27781 15297
      10 5260 28625 14891
      20 5450 30469 15078
      50 5553 35391 15735
      100 6193 43203 16734
      200 7674 56297 18828
      400 10646 90656 22906
      600 13326 142766 23407
      800 14798 175343 23296
      1000 18937 248329 25235

      The 3rd column figures get bigger faster.

      The problem isn't just related to the number of threads, but also
      the number of objects being created per thread. If we drop the total
      number being created by 1 or 2 orders of magnitude the problem does away.

      Here's a sample program that reproduces the problem. Just compile
      and run - it produces a log file JVMTests6F.log with the times per thread.

      We noticed that the user percentage of total cpu being used is close
      to 100% for sparc and IBM JVM on PC, but only about 50% with increasing
      threads on Sun JVM on PC. Something is consuming lots of time.

      The type of object being created in the loop doesn't seem to matter.
      We've tried an int array, a user defined object, and a single Integer.
      All exhibit the problem, but primitive types don't (e.g. a single int doesn't).

      import java.util.*;
      import java.io.*;


      // JVM Test case 6F.
      // Copyright Paul Brebner, CSIRO Australia, 2000.
      /*

      Reveals poor Sun JVM performance on NT 4.0.
      Runs test from 1 to 1000 concurrent threads.
      Each thread has a loop which creates an object (e.g. an int array)
         lots of times. The number of times is (by default) 100 million/number of
      threads.

      The poor performance seems to start from about 10 million iterations
      (and therefor objects) upwards. Less than this doesn't bother it.

      With 100 million iterations the user time is only about 50% total
      cpu on NT.


      */
      public class JVMTests6F extends Thread
      {
          static boolean logToFile = true;
          
          static int totalTime = 0;
         
         
          static int runs[] = {1, 2, 5, 10, 20, 50, 100, 200, 400, 600, 800, 1000};
              
         
          public static int maxThreads = 0; // Number of desired concurrent threads.
          public static int totalThreads = 0; // Total threads created in complete
      run.
          public static boolean compute = false;
          
          
          static int numIts = 0; // Number of iterations per thread.
          
          static String test_msg;
         
          private int tnum;
          private int doits;
          
          private static boolean printThreads = true;
          public static PrintWriter out;
         
       public JVMTests6F(int threadNum, int its)
       {
          doits = its;
          tnum = threadNum;
       }
           
       public static void main(String args[])
       {
         
          
           if (logToFile)
           try {
                   out = new PrintWriter (new BufferedWriter (new FileWriter
      ("JVMTests6F.log", false)));
           }
           catch (Exception e) {System.out.println("File creation failed!"); logToFile
      = false; }
          
          
       
          test6();
        
         
         System.out.println("Total test time = " + totalTime);
         if (logToFile) out.println("Total test time = " + totalTime);
         if (logToFile)
          out.close();
       }
       

       static void test6()
       {
           test6F();
       }
       
       
       static void test6F()
       {
         int initIts = 100000000;
         
         // Let iterations works o.k. e.g. 10 million
        // int initIts = 10000000;
         
          test_msg = "Test 6F: Concurrent threads, Object created in for loop";
        
          print_config();
         
          for (int i = 0; i < runs.length; i++)
          {
              maxThreads = runs[i];
              totalThreads = maxThreads;
              numIts = initIts / maxThreads;
              System.out.println("Threads = " + totalThreads + ", Total iterations = "
      + initIts + ", iterations/thread = " + numIts);
              testThreads();
          }
       
         
       }

       
       static void print_config()
       {
          System.out.println(
                  test_msg
              );
              
              if (logToFile)
              out.println(
                  test_msg
              );
       }
       

       public static void testThreads()
       {
          JVMTests6F thread;
          
          JVMTests6F threads[] = new JVMTests6F[maxThreads];
        
          TimerLocal timer = new TimerLocal();
          timer.start();
         
          if (logToFile) out.print(maxThreads + ", ");
          
          int t = 0;
          
          // create threads
          for (int count=0; count < maxThreads; count++)
          {
          
                  thread = new JVMTests6F(count, numIts);
                  threads[count] = thread;
          }
          
          // run threads
          for (int count=0; count < maxThreads; count++)
          {
              threads[count].start();
          }
          
          // join threads
          for (int count=0; count < maxThreads; count++)
          {
              try {
              threads[count].join();
              }
              catch (Exception e) {};
          }
             
          
      timer.stop();
      System.out.println("All done! Total Time = " + timer.getEllapsed());
      if (logToFile)
      {
      out.println(timer.getEllapsed());
      out.flush();
      }
              
          totalTime += timer.getEllapsed();
       }
       
       
       public void run()
       {
          for (int iteration=0; iteration < doits; iteration++)
          {
              // A few variations:
              // Any non-primitive type slows it down.
              // E.g. int array, user defined object, or even a single
              // Integer object!
              // Remove comments to try different examples.
              // Note compute always false so values are used
              // in this version of the test.
             
             // int array example (original)
             /*
             int values[] = {1, 10, -20, 500, -10, 200, 5000, 1000, -100};
           
           
             int values[] = {};
             if (compute)
             {
                 int i = 0;
                 for (int j=0; j < values.length; j++)
                  i += values[j];
                  System.out.println("i = " + i);
             }
             */
             
             // user defined object example
             /*
             TimerLocal tt = new TimerLocal();
             if (compute)
             {
                  tt.start();
                  tt.stop();
             }
             */
             
             // single Integer object
             Integer i = new Integer(10);
             if (compute)
             {
              System.out.println(i);
             }
          }
        
          return;
       }
       

      }


      class TimerLocal
      {
          // time in milli-seconds
          private long ellapsed;

          // time in milli-seconds
          private long time0 = 0;

          public TimerLocal() {}

          synchronized public void start()
          {
      time0 = System.currentTimeMillis();
          }

          synchronized public void stop()
          {
      ellapsed = System.currentTimeMillis() - time0;
          }

          synchronized public long getEllapsed()
          {
      return ellapsed;
          }

          synchronized public long getTime0()
          {
      return time0;
          }
      }
      (Review ID: 112969)
      ======================================================================

            tcramersunw Timothy Cramer (Inactive)
            kryansunw Kevin Ryan (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: