2
头图

Java has two methods for System.currentTimeMillis() timestamps: 061e924424048e and System.nanoTime() . Their usage scenarios are different. Some articles on the Internet currently have some one-sided descriptions of the performance discussions of these two methods. This article hopes to give a simple final Answer.

System.currentTimeMillis() has performance issues?

the answer is negative. The difference in performance between these two methods depends on the operating system.

Windows:

Under Windows, System.currentTimeMillis() is System.nanoTime() , because the Windows system only provides a cache variable for the former, while the latter is real-time to get the count from the bottom of the hardware.

So if your production environment is Windows, please avoid using System.nanoTime() as much as possible.

Linux:

Under Linux, the execution time of the two is not much different, whether it is single-threaded or multi-threaded.

Different virtual machine implementations will bring performance differences

Today's cloud hosts mainly have two implementations, Xen and KVM. Some articles on the Internet found that they have performance differences in taking system time.

Article address: https://www.javaadvent.com/2019/12/measuring-time-from-java-to-kernel-and-back.html

When your virtual machine is using Xen, the time-consuming time will be more than ten times that of KVM. However, the above also provides solutions on how to solve such problems.

Need to write a special class to improve System.currentTimeMillis() performance?

unnecessary. That is superfluous.

my test code

My test code is as follows, without any dependencies, it can be compiled and run directly with javac. Readers who are interested can try:

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

public class TimePerformance {

    public static final int LOOP_COUNT = 9999999;
    public static final int THREAD_COUNT = 30;

    public static void main(String[] args) {

        Runnable millisTest = () -> {

            long start = System.currentTimeMillis();
            for (int i = 0; i < LOOP_COUNT; i++) {
                System.currentTimeMillis();
            }
            long end = System.currentTimeMillis();

            System.out.printf("%s : %f ns per call\n",
                    Thread.currentThread().getName(), ((double)end - start) * 1000000 / LOOP_COUNT);
        };

        Runnable nanoTest = () -> {

            long start = System.currentTimeMillis();
            for (int i = 0; i < LOOP_COUNT; i++) {
                System.nanoTime();
            }
            long end = System.currentTimeMillis();

            System.out.printf("%s : %f ns per call\n",
                    Thread.currentThread().getName(), ((double)end - start) * 1000000 / LOOP_COUNT);
        };

        Consumer<Runnable> testing = test -> {
            System.out.println("Single thread test:");
            test.run();

            System.out.println(THREAD_COUNT + " threads test:");
            List<Thread> threads = new ArrayList<>();
            for (int i = 0; i < THREAD_COUNT; i++) {
                Thread t = new Thread(test);
                t.start();
                threads.add(t);
            }
            // Wait for all threads to finish
            threads.forEach(thread -> {
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        };

        System.out.println("//// Test System.nanoTime()");
        testing.accept(nanoTest);
        System.out.println("//// Test System.currentTimeMillis()");
        testing.accept(millisTest);
    }
}

Because I am using Windows, System.nanoTime() obviously very slow in the execution output. I will not release the specific output content, because it has no reference value, and most production environments use Linux.


捏造的信仰
2.8k 声望272 粉丝

Java 开发人员