JMeter的nanoThreadSleep属性 - 我该如何使用它?

时间:2015-03-05 21:54:17

标签: performance jmeter benchmarking jmeter-plugins nanotime

我正在设置一个负载测试解决方案,正如我一直在阅读JMeter的文档,我看到你可以为测试计划设置很多属性。我已经测试已经运行得很好并产生结果,图表等,但是当我试图更深入地了解JMeter和结果的准确性等时,我遇到了下面的模糊。

JMeter's documentation开始,我阅读了以下内容:

# Whether to use System.nanoTime() - otherwise only use System.currentTimeMillis()
sampleresult.useNanoTime=true

# Use a background thread to calculate the nanoTime offset
# Set this to <= 0 to disable the background thread
sampleresult.nanoThreadSleep=5000

现在,我知道nanotime将基于固定但任意的原始时间,而currenttimeinmillis则基于系统时间(即挂钟)。而且我知道nanotime会更精确,这就是我对使用它感兴趣的原因:我正在进行负载测试,并且需要响应时间测量尽可能准确和精确。

但我遇到的问题是了解如何使用nanoThreadSleep。纳米级偏移究竟是什么?为什么我想要或不想要后台线程来计算纳米级偏移?如果我启用JMeter使用纳米时间运行会发生什么,但是不要明确使用nanoThreadSleep设置?

我搜索了StackOverflow和Google的某些解释,但除了JMeter的文档在我粘贴的那个小小的模糊中找不到它之外我找不到。其他人可以帮助我理解这一点以及如何正确有效地使用它吗?

1 个答案:

答案 0 :(得分:1)

查看JMeter代码,我发现下面的部分是感兴趣的部分。所以基本上后台线程是睡眠NANOTHREAD_SLEEP毫秒然后当它醒来时,它询问时间。

该值必须保持尽可能高,以免增加采样的开销,但必须保持尽可能低以提供足够的精度。

如果您不使用纳米线程,则所有时间都是使用System.nanoTime()计算的,这可能会或可能不会提供额外的准确性。通常,高精度计数器受频率变化的影响很大(例如,由于省电模式)。我的观点是,您不必担心使用System.nanoTime(),因为您无法以纳秒级别的准确度获得测试的可重复性。甚至毫秒似乎是一个非常紧张的间隔。

为什么你会使用后台线程来计算时间?我认为这是因为如果线程只测量时间,你可以在执行期间随时询问当前时间。如果你不使用后台线程,我认为时间只在采样点更新。启用线程后,我认为时间会更频繁地更新(考虑到NANOTHREAD_SLEEP已充分考虑)。我还没有写过JMeter,但我认为这是时间线程背后的哲学。

这有用吗?可能会挤出额外的准确度。但是,JMeter用于测试Web应用程序的性能,由于网络延迟,资源使用等导致可重复性差,。即使你测量纳秒,人们也会对秒和毫秒部分感兴趣,并且测试是可重复的。

<强> CODE:

private static class NanoOffset extends Thread {

    private static volatile long nanoOffset; 

    static long getNanoOffset() {
        return nanoOffset;
    }

    @Override
    public void run() {
        // Wait longer than a clock pulse (generally 10-15ms)
        getOffset(30L); // Catch an early clock pulse to reduce slop.
        while(true) {
            getOffset(NANOTHREAD_SLEEP); // Can now afford to wait a bit longer between checks
        }
    }

    private void getOffset(long wait) {
        try {
            TimeUnit.MILLISECONDS.sleep(wait);
            long clock = System.currentTimeMillis();
            long nano = SampleResult.sampleNsClockInMs();
            nanoOffset = clock - nano;
        } catch (InterruptedException ignore) {
            // ignored
        }
    }        
}