2

I have successfully deployed a java service onto a Linux distribution based on the guide here i.e. the actual simple file IO tick-tock code, and am noticing high CPU usage for such a simple program. Perhaps due to the thread constantly checking...

I have built the actual JAR file on CentOS using NetBeans and then deployed onto Arch Linux ARM distribution, and then using a) Oracle's Java SE Embedded JVM (v7) and b) java-7-openjdk JVM.

The issue is that CPU usage is constantly rocking between 80 and 95% by jsvc. I wouldn't expect the CPU to go that high. In the actual jsvc call I tried adding the -server parameter for background process - but did not manage to (I get . An example for this would be helpful so that we can rule out whether it is the missing -server parameter or not.

I think I may be missing something apart from the -server option. I've been told to look at ScheduledExecutorService - which can make an improvement perhaps?

Your thoughts are appreciated - Thanks.

gc_i
  • 41
  • 1
  • 6
  • You should change your approach from trying to find a knob that can turn down the CPU usage, to finding out what and why the CPU usage is high. It might be as simple as the code having a bug, a particular inefficient inner loop, or simply the processor being (too) slow. – nos Feb 16 '14 at 20:58
  • Thanks for the hint nos. I am not sure what's under the hood of jsvc, and I have provided the link to the actual daemon code. I suspect that the thread is constantly checking the file for the last tick/tock before adding another one ( while(!stopped){...} loop ). So (a) I need to verify if this is the case and (b) any little optimization helps - so in terms of setup i.e. JVM used and actual parameters passed,such as -server / -client or perhaps the heap size, should have an impact (even if smaller). Based on the above, views on the best practice on how to do this properly would be appreciated. – gc_i Feb 16 '14 at 21:06
  • if you're using the actual code there, it contains an infinite loop that spins the CPU as fast as it can. I'd do a Thread.Sleep(1000); call in the run() method. – nos Feb 16 '14 at 21:11
  • Indeed! :) This actually worked when added in the run() method, specifically within the while loop. Thanks! - will post the answer as soon as I have enough credits. – gc_i Feb 16 '14 at 21:44

2 Answers2

1

So on nos suggestion I added the Thread pause and it fixed the issue. Code as follows:

        @Override
        public void run() {                 

            while(!stopped){

                long now = System.currentTimeMillis();
                if(now - lastTick >= 10000){
                    System.out.println(!lastOneWasATick ? "tick" : "tock");
                    lastOneWasATick = !lastOneWasATick;
                    lastTick = now; 
                }

                //ADDED THIS BLOCK
                try {
                    Thread.sleep(15000);
                } catch (InterruptedException ex) {
                    //Logger.getLogger(JDaemon.class.getName()).log(Level.SEVERE, null, ex);
                }
                //END BLOCK
            }

        }
gc_i
  • 41
  • 1
  • 6
1

Depending on what you're doing, The Thread.sleep method is probably fine, but I would still recommend using the ScheduledExecutorService.scheduleAtFixedRate() method. It has been thoroughly tested, documented and other developers that might need to maintain your code in the future should be familiar with it. It also provides methods to cancel execution for example and to manage more than one task. I'd give it a closer look.

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import static java.util.concurrent.TimeUnit.*;

public class Clock {

    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    private boolean lastOneWasATick = false;

    public void startClock() {

        //Define the task 
        final Runnable tickTock = new Runnable() {
            public void run() {
                System.out.println(!lastOneWasATick ? "tick" : "tock");
                lastOneWasATick = !lastOneWasATick;
            }
        };      

        //Schedule the task's execution at 1 second intervals, starting immediately
        final ScheduledFuture<?> tickTockThreadHandle = scheduler.scheduleAtFixedRate(tickTock, 0, 1, SECONDS);

        //Stop the clock after 1 minute
        scheduler.schedule(new Runnable() {
            public void run() {
                tickTockThreadHandle.cancel(true);
            }
        }, 60, SECONDS);
    }
}
Sheldon Neilson
  • 803
  • 4
  • 8