0

How can I get the CPU utilisation more constant?

I would like to generate an artificial load with java which stresses the CPU and consumes RAM. It is important that the resource consumption stays constant. The focus hereby is on the CPU. RAM is secondary. I chose Java since it can run on almost every platform. I am interested to see if this load on my computer for example constantly consumes 20% of the CPU utilization per hour, but on my second computer maybe 30%. To achieve higher CPU utilization and stress multiple cores the program runs with multiple threads.

I have already read generate CPU load in Java and Artificial generation of cpu load in Java asked on stackoverflow.

Here is my code. I have one class to control the threads and one class for the threads providing the load. I chose to calculate factorial to stress CPU.

package loadPackage;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class LoadController {

    public static void main(String[] args) {
        int threads = 16;
        int runlength = 100000;
        long time;
        try {
            runlength = Integer.parseInt(args[0]);
        } catch (Exception e) {
            System.out.println("Only integer allowed!");
        }
        time = System.currentTimeMillis() + runlength;
        ExecutorService executor = Executors.newFixedThreadPool(threads);
        for (int i = 0; i < threads; i++) {
            Runnable worker = new Workload(time);
            executor.execute(worker);
          }
        executor.shutdown();
        while (!executor.isTerminated()) {
        }

    }

}



package loadPackage;

import java.math.BigInteger;

public class Workload implements Runnable  {
    private long time;

    public Workload(long time) {
        this.time = time;
    }

    public void run() {
        while (System.currentTimeMillis() < time) {
            BigInteger fact = BigInteger.valueOf(1);
            for (int i = 1; i <= 6000; i++) {
                fact = fact.multiply(BigInteger.valueOf(i));
            }
            try {
                Thread.sleep(200);
            }
            catch (Exception localException1) {}
        }
    }

}

My measurement tool measures every 5min (not a sample but the average utilization in this period). So minimal variation can be tolerated. But still, sometimes it shows strong peaks I cannot explain.

Question one: Do you know why my CPU utilization could have such strong peaks?

Question two: What programming techniques can I use to minimize CPU utilization deviation?


[Update 04-30-2015]

My assumption to question one cause: Hyper Threading
I have a HP laptop i7 quad-core with hyper threading (task manager shows 8 virtual cores). The measuring tool I use has a hyper threading correction and shows the actual resources consumed. Whereas, this is a guess, VisualVM only measures the virtual core consumption!? I tried to deactivate hyper threading in BIOS to proof the correctness of my assumption. But thanks to HP this option is not available under configuration in BIOS. What do you think, is hyper threading the cause of the measurement deviation?

Alternative approach: different JVM
I am using the standard JVM "Java HotSpot(TM) 64-Bit Server VM". Would useing a more compact JVM contribute to a more stable Java resource consumption?

Community
  • 1
  • 1
Incanus
  • 389
  • 1
  • 4
  • 16
  • Not sure if such a program is possible. Even if you managed to write one, how would you make sure other external factors are constant? How would you make sure the OS does not consume any CPU cycles? How do you account for the CPU cycles consumed by a profiler? – Chetan Kinger Apr 23 '15 at 13:36
  • What version of Java you using? – Sleiman Jneidi Apr 23 '15 at 13:37
  • @bot I printet out the milliseconds for each iteration of my while loop of each thread. most of the time the execution time only differed by 1-3 milliseconds. and then then there where some small huge jumps. I tried to run the threads with higher priority but still. I played around with the parameters of the sleep time and the factorial so that the cpu utilization is not too high and OS can still get resources. But I dont know if the peaks come from java itself or another process "stealing" cpu time. I have an i7 with four cores, 8 virtuals in total. – Incanus Apr 23 '15 at 14:27
  • @SleimanJneidi I am using Java 6.0.240.7 – Incanus Apr 23 '15 at 14:28

3 Answers3

0

CPU utilization is managed by the OS, so AFAIK there is no way to 'lock' a java thread to a specific processor (which would result in constant utilization). You will see this when you open htop on a linux system. The thread will be jumping like a cricket over your cpus. I've never managed to accomplish such constant utilization in java, only in C(++).

Liebertee
  • 88
  • 9
  • So you are saying the key is to switch to C++ ? Is it due to Java JVM and the interpreter and C++ being compiled? If I switch to C++ what would be the key to accomplish such constant utilization there? What does C++ provide that Java does not? – Incanus Apr 23 '15 at 14:43
  • Well, in C you basically write code closer to the underlying hardware. In Java you still have the additional Interpreter. Plus, i havent seen methods in Java which enable me to run THIS Thread on THAT core. Because the scheduler of your OS is making that decision. Maybe you should look for a different JVM? There are several. – Liebertee Apr 23 '15 at 20:21
0

I would recommend you to launch visual vm for example during the process. You will be able to track the GC activity. If you see a GC peak which consume as CPU time as you saw before, you could establish that's the cause.

Steph
  • 779
  • 1
  • 8
  • 18
  • Hi Steph, I analyzed my program with VisualVM. Thanks for the advice. The weird thing is, those peaks I measured with the other tool are not visible in VisualVM. I additionally used the Tracer plugin. Using Tracer, it seems that my load is pretty constant. Sometimes GC kicks in and causes minor peaks. But that is bearable. What I guess is, that the explaination of the strong peaks in the original measuring tool I have used come from hyper threading. – Incanus Apr 30 '15 at 09:53
  • It's interesting. It's hard to make quickly a conclusion, that's why it's easier to eliminate some doubts with some tools. – Steph Apr 30 '15 at 10:05
  • I updated my question above and added the possible root cause of hyper threading. Do you know a java profile that takes HT in account and is easy to use? VisualVM probably displays only the virtual CPU consumption, or am I wrong? – Incanus Apr 30 '15 at 14:29
  • No I don't. I would try to disable hyper threading and test again but I read you have already done that – Steph Apr 30 '15 at 15:42
0

I know this a bit old thread, but if you are still interested, have a look at OpenHFT Java thread affinity library at https://github.com/OpenHFT/Java-Thread-Affinity. I've used this to pin Java threads to given cores and yield good performance (CPU usage) for certain applications.

As suggested in the author's blog (http://vanillajava.blogspot.com/2011/12/thread-affinity-library-for-java.html) having isolated cores (you can pass isolcpus= at boot time) will be helpful too.

Saliya Ekanayake
  • 387
  • 3
  • 10