Linux 上的 Java : Measuring elapsed time using System. nanotime() 用于阻塞线程

标签 java linux benchmarking

我有一个线程从 ArrayBlockingQueue() connectionPool. 获取一个对象如果 ArrayBlockingQueue() 为空,则线程可能会被阻塞。为了测量调用线程被阻塞的时间,我使用以下代码:

long start = System.nanoTime();
DataBaseEndPoint dbep = connectionPool.take();
long end = System.nanoTime();
long elapsed = (end - start)/1000000;

现在,我担心的是,未阻塞的线程可能会开始在多处理器计算机中的不同处理器上运行。在这种情况下,我不完全确定使用的“系统计时器”在不同处理器上是否相同。 这篇博客文章 ( http://www.javacodegeeks.com/2012/02/what-is-behind-systemnanotime.html ) 建议 Linux 对每个处理器使用不同的时间戳计数器(也用于 System.nanotime()),这确实会扰乱上面示例中的耗时计算。

The value is read from clock_gettime with CLOCK_MONOTONIC flag Which uses either TSC or HPET. The only difference with Windows is that Linux not even trying to sync values of TSC read from different CPUs, it just returns it as it is. It means that value can leap back and jump forward with dependency of CPU where it is read.

但是,此链接 ( http://lwn.net/Articles/209101/ ) 表明 TSC 不再用于高分辨率计时器。

... the recently-updated high-resolution timers and dynamic tick patch set includes a change which disables use of the TSC. It seems that the high-resolution timers and dynamic tick features are incompatible with the TSC...

所以,问题是,Linux 机器使用什么来将值返回到 System.nanotime()现在?并且,正在使用System.nanotime()在上述情况下可以安全地测量耗时(在另一个处理器上启动的阻塞线程)。如果不安全,还有什么替代方案?

最佳答案

虚拟机(以及一般生活)的一个无价之宝就是抽象。线程的执行时间不会根据核心数量而有所不同;不在 Linux 中,也不在 Windows 等中......我希望我没有误解你的问题。

(虽然我使用的是currentTimeMillis(),当然,不同尺度的纳米时间是相同的)

检查我制作的以下示例:

public class SynchThreads {

    public static void main(String[] args) throws InterruptedException {
        GreedyTask gtA = new GreedyTask("A");
        GreedyTask gtB = new GreedyTask("B");
        Thread a = new Thread(gtA);
        Thread b = new Thread(gtB);
        a.start();
        b.start();
        a.join();
        b.join();
        System.out.println(gtA.toString()+" running time: "+gtA.getRunningTime());
        System.out.println(gtB.toString()+" running time: "+gtB.getRunningTime());
    }

    private static class GreedyTask implements Runnable {

        private long startedTime, finishedTime, totalRunTime;
        private String myName;

        public GreedyTask(String pstrName) {
            myName = pstrName;
        }

        public void run() {
            try {
                startedTime = System.currentTimeMillis();
                randomPowerNap(this);
                finishedTime = System.currentTimeMillis();
                totalRunTime = finishedTime - startedTime;
            } catch (Exception e) { System.err.println(e.getMessage()); }
        }

        public String toString() { return ("Task: " + myName); }
        public long getRunningTime() { return this.totalRunTime; }
    }

    private static synchronized void randomPowerNap(GreedyTask gt) throws       InterruptedException {
        System.out.println("Executing: "+gt.toString());
        long random = Math.round(Math.random()*15000);
        System.out.println("Random time for "+gt+" is: "+random);
        Thread.sleep(random);
    }
}

以下是在 4 核 Windows 机器上运行的输出:

Executing: Task: A
Random time for Task: A is: 1225
Executing: Task: B
Random time for Task: B is: 4383
Task: A running time: 1226
Task: B running time: 5609 // what's funny about this? this is equal to Btime - Atime

这是在 4 核 Linux 机器上运行的:

Executing: Task: A
Random time for Task: A is: 13577
Executing: Task: B
Random time for Task: B is: 5340
Task: A running time: 13579
Task: B running time: 18920 // same results

结论:B 总时间增加了 randomPowerNap 被 A 阻塞时必须等待的时间,因此,由于虚拟机的硬件抽象,线程的运行时间没有差异,因为它们都在“虚拟大核心”中运行,如果你明白我的意思的话。

我希望这有帮助。

关于Linux 上的 Java : Measuring elapsed time using System. nanotime() 用于阻塞线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20557511/

相关文章:

java - J2EE Struts、Spring 和 Hibernate 框架问题

java - 使用 JasperReports 创建具有样式的 Excel

java - 如何改变java定时器的时间间隔

linux - Linux 中 tcpip 堆栈的多个实例

c - memcpy - 从不同大小的整数转换为指针

c++ - 使用 C++11 的可移植定时代码的正确方法

machine-learning - 深度学习基准测试在 16 位和 8 位定点精度下的表现如何?

java - GridBag布局辅助

linux - bash shell 脚本中的意外输出

java - Java 获取数组列表中前 k 项的最有效方法