How long it takes for one second in Java? Measure

2019-05-04 17:40发布

I don't want to change this code, I'm only interested in JVM, OS or kernel customization/configuration for best results!


I have one second loop (1000 x 1ms)

public static void main(String[] args) throws InterruptedException {
    long start = System.nanoTime();
    for (int i = 0; i < 1000; i++ ) {
        Thread.sleep(TimeUnit.MILLISECONDS.toMillis(1));
    }
    long duration = System.nanoTime()  - start;
    System.out.println("Loop duration " + 
         duration / TimeUnit.MILLISECONDS.toNanos(1) + " ms.");
}

On my Fedora 20 with kernel 3.12 this loop needs 1055 ms.

This is pretty good result, average is more than 1100ms.

Is possible to make this code faster with custom JVM flags or OS configuration?

Loop duration 1055 ms.

8条回答
对你真心纯属浪费
2楼-- · 2019-05-04 17:42

Calling sleep() you are basically telling the OS to suspend your thread for AT LEAST X milliseconds. There is no guarantee whatsoever that it will continue executing exactly after this time or the OS will re-scheadule your thread later. Furthermore, the minimum amount of sleep time and its accuracy heavily depends on the OS.

EDIT: Also you should take into account that in your case , (most probably) your code is being interpreted! JAva compiles to native code only hotspots (and fromm here comes the name of the Hotspot JIT) which are being executed frequently. For server VM, this is 10k executions of a given code. You only have 1k.

查看更多
走好不送
3楼-- · 2019-05-04 17:45

System.currentTimeMillis should not be used as a measure of elapsed time. You should be using System.nanoTime. Look here for a bit more explanation.

查看更多
仙女界的扛把子
4楼-- · 2019-05-04 17:47

Well, you could obviously factor out the TimeUnit conversion and save a few cycles. You could also count down rather than up; using a !=0 test is usually faster than comparing to other values.

You should also make sure the code is fully JITted (which can take several minutes of running it) before you take ANY measurements.

Generally, microbenchmarks are misleading in Java, and microoptimizing without knowing how much that code contributes to your runtime tends to be wasted effort in any case. Don't bother with this sort of exercise. Write the best code you can, give it lots of warm-up time on an assortment real data, then use a profiler to see where it's spending its time (also on real data). That will tell you where performance tuning will actually be productive. Then consider algorithmic improvements, which tend to yield the highest benefit. Profile again with the new code and see what is hot now. Repeat.

Remember, infinite improvement of something that accounts for 1% of runtime takes infinite effort but yields only 1% improvement. Put your effort where it makes a difference. And, especially in hotspot Javas where code continues to be optimized during execution but that optimization is not fully deterministic, don't trust a single execution to give you real performance numbers.

查看更多
够拽才男人
5楼-- · 2019-05-04 17:50

By my knowledge, one of the factors here is the kernel system tick time (I think it's 200 tps for desktops, 100 for servers, and 1000 forRT systems). This causes small delays which accumulate up to the 55 ms. Additionally, the sleep call will have some system overhead, which is hard to reduce by itself.

查看更多
冷血范
6楼-- · 2019-05-04 17:55

Why don't you simply put it into one single sleep?

Thread.sleep(1000);

I you really want to do 1000 sleep commands I recommend this:

public static void main(String[] args) throws InterruptedException {

    // This line is for timing reasons only!
    long start = System.currentTimeMillis();

    final long startTime = System.currentTimeMillis();
    long waitTime;

    for (int i = 0; i < 1000; i++ ) {
        // Get the time you want to end with. Then substact your current system time!
        waitTime = (startTime + i + 1)- System.currentTimeMillis();

        // Only wait if it would wait (If waitTime is greater than 0.
        // Everything below 0 will also throw a execption!
        if(waitTime > 0)
            Thread.sleep(waitTime);
    }

    // Same for those...
    long duration = System.currentTimeMillis() - start;
    System.out.println("Loop duration " + duration + " ms.");

}

This will make sure you only wait if that makes currently sense!

查看更多
做个烂人
7楼-- · 2019-05-04 18:03

Unfortunately, my question was misunderstood.

Realtime java is abandoned, so advice for using Realtime java is not valid.

After some researches this test has best results on some Windows machines.

On tested Windows 8.1 this tests prints exactly 1000ms.

Other results:

  • Mac Os X 10.9.1 with Java 1.7.0_25 : 1180 - 1190ms
  • Ubuntu 12.04/Corei3/4GB : 1122 ms

References

查看更多
登录 后发表回答