Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JMeter's nanoThreadSleep Property - How do I use it?

I'm setting up a load testing solution, and as I've been reading through JMeter's docs, I see that you can set numerous properties for test plans. I've got tests already running just fine and producing results, graphs, etc., but as I tried to gain a more in-depth understanding of JMeter and accuracy of results and such, I come across the blurb below.

From JMeter's documentation, I read the following:

# 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

Now, I understand that nanotime is going to be based off of a fixed, but arbitrary, origin time, whereas currenttimeinmillis is based off of system time (i.e., wallclock). And I know that nanotime is going to be more precise, which is why I'm interested in using it: I'm doing load testing and need the response time measurements to be as accurate and precise as possible.

But the issue I'm having is understanding how to use nanoThreadSleep. What exactly is a nanotime offset? Why would i want, or not want, a background thread to calculate the nanotime offset? What happens if I enable JMeter to run using nanotime, but don't use the nanoThreadSleep setting explicitly?

I've searched StackOverflow and Google for some sort of explanation, but I cannot find one other than what JMeter's docs say about it in the tiny blurb I pasted here. Can others help me in understanding this and how I can use it correctly and effectively?

like image 241
liltitus27 Avatar asked Nov 10 '22 18:11

liltitus27


1 Answers

Looking at JMeter code, I found the section below to be the one of interest. So basically the background thread is one that sleeps for NANOTHREAD_SLEEP milliseconds and then when it wakes up, it asks the time.

This value has to stay as high as possible not to add to much overhead to the sampling, but has to stay as low as possible to provide sufficient accuracy.

If you don't use the nanothread, then all the times are computed using System.nanoTime() and that may or may not give extra accuracy. Generally the high precision counters are very affected by frequency variations (e.g. due to power saving modes). My opinion is that you don't need to worry about using System.nanoTime() because you won't be able to have a repeatability of the test with an accuracy at nanosecond level. Even millisecond seems a very tight interval for that.

Why would you use a background thread for computing time? I think this is because if the thread only measures time, you can ask it the current time anytime you want during the execution. If you don't use the background thread, I think the time is updated only at the point of sampling. With the thread enabled I think this the time is updated more frequently (provided NANOTHREAD_SLEEP is well considered). I haven't wrote JMeter but I think this is the philosophy behind the time thread.

Is this useful? Probably it can squeeze extra accuracy. However, JMeter is used for testing performances of Web applications, where repeatability is poor due to network delays, resource usages, etc. Even if you measure nanoseconds, people will be interested more in the seconds and milliseconds part and that the test is repeatable.

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
        }
    }        
}
like image 104
VAndrei Avatar answered Nov 15 '22 06:11

VAndrei