JVM Tutorials - Herong's Tutorial Examples - Version 4.23, by Dr. Herong Yang
CPU Intensive Process - 1 Thread per CPU
This section provides a tutorial example on how to test the overall productivity of multithreading CPU intensive processe. Running 1 thread per CPU gives the most effective outcome.
Now, I can easily write a multithreading controlling program to run multiple instances of PrimeCalculator.java concurrently.
/* MultithreadingCpuRunner.java * Copyright (c) 2014, HerongYang.com, All Rights Reserved. */ public class MultithreadingCpuRunner { public static void main(String[] a) { // Setting configuration long param = 1000; // Default parameter for the working thread int size = 1; // Default number of working threads int interval = 1; // Default monitoring interval in seconds if (a.length>0) param = Long.parseLong(a[0]); if (a.length>1) size = Integer.parseInt(a[1]); if (a.length>2) interval = Integer.parseInt(a[2]); System.out.println("Thread parameter: "+param); System.out.println("Number of threads: "+size); // Launching all threads PrimeCalculator[] threads = new PrimeCalculator[size]; long[] counts = new long[size]; for (int i=0; i<size; i++) { PrimeCalculator t = new PrimeCalculator(param); t.start(); threads[i] = t; counts[i] = 0; } // Monitoring overall productivity long startTime = System.currentTimeMillis(); long lastTime = startTime; long grandTotal = 0; System.out.println( "Seconds | Productivity per thread | Total | Average"); while (true) { try { Thread.sleep(interval*1000); } catch (InterruptedException e) { System.out.println("Monitor interrupted."); } long curTime = System.currentTimeMillis(); long delta = (curTime - lastTime); long duration = (curTime - startTime); System.out.print(duration/1000+" | "); long total = 0; for (int i=0; i<size; i++) { long c = threads[i].jobCount; long d = c - counts[i]; total += d; System.out.print((1000*d)/delta+" "); counts[i] = c; } grandTotal += total; System.out.println("| "+(1000*total)/delta +" | "+(1000*grandTotal)/duration); lastTime = curTime; } } }
Some notes on MultithreadingCpuRunner.java:
Now, let's run MultithreadingCpuRunner.java with different numbers of threads:
C:\>"\Program Files\Java\jdk1.7.0_45\bin\java" MultithreadingCpuRunner 1000 1 Thread parameter: 1000 Number of threads: 1 Seconds | Productivity per thread | Total | Average ... 181 | 883 | 883 | 885 182 | 890 | 890 | 885 183 | 886 | 886 | 885 184 | 882 | 882 | 885 185 | 888 | 888 | 885 ... C:\>"\Program Files\Java\jdk1.7.0_45\bin\java" MultithreadingCpuRunner 1000 2 Thread parameter: 1000 Number of threads: 2 Seconds | Productivity per thread | Total | Average ... 201 | 841 841 | 1682 | 1665 202 | 840 840 | 1680 | 1665 203 | 841 840 | 1681 | 1665 204 | 830 819 | 1649 | 1665 205 | 841 841 | 1682 | 1665 ... C:\>"\Program Files\Java\jdk1.7.0_45\bin\java" MultithreadingCpuRunner 1000 4 Thread parameter: 1000 Number of threads: 4 Seconds | Productivity per thread | Total | Average ... 211 | 462 463 467 468 | 1861 | 1857 212 | 450 463 467 467 | 1849 | 1857 213 | 464 464 468 469 | 1866 | 1857 214 | 466 466 466 466 | 1865 | 1857 215 | 466 464 467 466 | 1865 | 1857 ... C:\>"\Program Files\Java\jdk1.7.0_45\bin\java" MultithreadingCpuRunner 1000 8 Thread parameter: 1000 Number of threads: 8 Seconds | Productivity per thread | Total | Average ... 235 | 159 467 143 470 158 158 164 145 | 1868 | 1855 236 | 150 462 142 466 157 152 153 154 | 1840 | 1855 237 | 143 461 156 464 155 152 144 164 | 1845 | 1855 238 | 158 464 149 465 142 163 171 142 | 1858 | 1855 239 | 177 465 146 466 149 142 166 143 | 1858 | 1855 ... C:\>"\Program Files\Java\jdk1.7.0_45\bin\java" MultithreadingCpuRunner 1000 16 Thread parameter: 1000 Number of threads: 16 Seconds | Productivity per thread | Total | Average ... 126 | 120 70 70 34 106 60 96 30 141 151 90 35 116 35... | 1545 | 1855 127 | 128 50 45 65 99 42 135 94 99 157 171 46 135 49... | 1854 | 1855 128 | 100 85 50 84 142 50 112 43 106 142 149 49 171 ... | 1853 | 1855 129 | 136 57 50 50 96 64 92 42 140 171 149 50 143 98... | 1859 | 1855 130 | 100 50 50 50 121 85 149 50 91 137 172 78 156 5... | 1860 | 1855 ...
If we take the average value in each test, we will get the following trend:
Threads Productivity Percent 1 885 100.00% 2 1665 188.14% 4 1857 209.83% 8 1855 209.60% 16 1855 209.60%
Here are my notes on these test results:
Conclusion: Multithreading CPU intensive processes does not improve overall productivity unless the JVM is running on a multi-CPU processor. In other words, if you have a 2-CPU processor, you should only run 2 CPU intensive processes concurrently.
Last update: 2014.
Table of Contents
Downloading and Installing JDK 1.8.0 on Windows
Downloading and Installing JDK 1.7.0 on Windows
java.lang.Runtime Class - The JVM Instance
java.lang.System Class - The Operating System
ClassLoader Class - Class Loaders
Class Class - Class Reflections
JRockit JVM 28.2.7 by Oracle Corporation
Memory Management and Garbage Collectors
JVM Stack, Frame and Stack Overflow
Thread Testing Program and Result
►CPU Impact of Multi-Thread Applications
PrimeCalculator.java - CPU Intensive Process
►CPU Intensive Process - 1 Thread per CPU
Single Thread Process on 2-CPU-4-Thread Machine
Two-Thread Process on 2-CPU-4-Thread Machine
Multi-Thread Process on 2-CPU-4-Thread Machine
Multi-Thread Process Slows Down System Response Time
Multi-Thread Process Running on JRockit JVM
I/O Impact of Multi-Thread Applications
Micro Benchmark Runner and JVM Options
Micro Benchmark Tests on "int" Operations
Micro Benchmark Tests on "long" Operations
Micro Benchmark Tests in JIT Compilation Mode