How to measure time taken by Java code? [duplicate] - java

This question already has answers here:
How do I write a correct micro-benchmark in Java?
(11 answers)
Closed 9 years ago.
I need to analyze complexity for some algorithms in Java. For that I am planning to give large number of input and measure the time taken by Java implementation. What is the most precise and accurate way to check time between some lines of code? I need precision in milliseconds...

You can get nanosecond resolution, even, using System.nanoTime().
However, you may want to consider the points in the following:
How do I write a correct micro-benchmark in Java?

Use a library such as Speed4j. This shall not only benchmark the calls but also provide statistics in logs, also you can see them remotely via JMX. It is better of using such a library rather than placing System.current.. calls all over the code.

Say you have a particular method that you would like to put under the microscope. You can do that as follows:
long time1 = System.nanoTime();
thatMethod();
long time2 = System.nanoTime();
long timeTaken = time2 - time1;
System.out.println("Time taken " + timeTaken + " ns");
Computers are really fast so it may happen that time difference when using getTimeMillis() maybe zero. Hence, use nanoTime()
You can also use Caliper. They have a video to get started. Plus, thoroughly read the answer pointed to by creichen. It has a lot of great stuff in it.

Use System.nanoTime() or System.currentTimeMillis() to get both start and finish time of your code. Be aware that micro-benchmarks measure only basic aspects of JVM performance. Be aware of warm up phase for JVM, after which JIT is started.

long start = System.currentTimeMillis();
// your code
long end = System.currentTimeMillis();
long diff = end-start;
or
long start = System.nanoTime();
// your code
long end = System.nanoTime();
long diff = end-start;
long diffInMillis = diff/1000000;

long startTime = System.currentTimeMillis();
//code lines whose time you want to calculate
long endTime = System.currentTimeMillis();
System.out.println("Took "+(endTime - startTime) + " ms");

Related

Calculate percentage completed at any given point of time based on estimated program end time in Java

I'm currently trying to implement progress of a long running process in Java.
Based on the current logic I'm trying to calculate approximate time when the program going to end based on using the time taken for single unit of calculation. For ex: I'm running a invoice progress to be sent to multiple vendors and each invoice takes 10s. So based on this I'll calculate the time for rest of the pending invoices.
I'm keeping the start time in milliseconds.
long startmillis = System.currentTimeMillis();
long finishmillisforsingleVendor = System.currentTimeMillis();
long elapsedTime = finishmillisforsingleVendor - startmillis;
long approximateEndTime = elapsedTime/1000 * 25;// trying to calculate in seconds and multiply with 25 remaining invoices.
This is the part I'm not sure. How would I use this elapsed time for single invoice to derive my program end time.
long percentageCompleted = System.currentTimeMillis()/1000 / approximateEndTime ;
I'm trying to calculate the percentage at any given point of time to show the user how much has been progressed so far. I'm not sure if this the right way to go.
Thanks
From the way you phrased your question, I suspect you're confusing a few terms. The percentage completed has nothing to do with elapsed time.
double percentComplete = 100.0*numberOfDocumentsCompleted/totalNumberOfDocuments;
Though, instead of a percentage, I would prefer a simple ratio:
double completionStatus = (double)numberOfDocumentsCompleted/totalNumberOfDocuments;
long elapsedMillis = System.currentTimeMillis() - startMillis;
long estimatedTotalMillis = (long) (elapsedMillis / completionStatus);
long remainingMillis = estimatedTotalMillis - elapsedMillis;

Calculating time difference in Milliseconds

I am making a call to a method by passing ipAddress and it will return back the location of ipAddress like Country, City, etc etc. So I was trying to see how much time it is taking for each call. So I set the start_time before making call to method and end_time after making a call. So sometimes I get difference as 0. And resp contains the valid response.
long start_time = System.currentTimeMillis();
resp = GeoLocationService.getLocationIp(ipAddress);
long end_time = System.currentTimeMillis();
long difference = end_time-start_time;
So that means sometimes it is taking 0 ms to get the response back. Any suggestions will be appreciated.
Try this
long start_time = System.nanoTime();
resp = GeoLocationService.getLocationByIp(ipAddress);
long end_time = System.nanoTime();
double difference = (end_time - start_time) / 1e6;
I pretty much like the (relatively) new java.time library: it's close to awesome, imho.
You can calculate a duration between two instants this way:
import java.time.*
Instant before = Instant.now();
// do stuff
Instant after = Instant.now();
long delta = Duration.between(before, after).toMillis(); // .toWhatsoever()
API is awesome, highly readable and intuitive.
Classes are thread-safe too. !
References: Oracle Tutorial, Java Magazine
No, it doesn't mean it's taking 0ms - it shows it's taking a smaller amount of time than you can measure with currentTimeMillis(). That may well be 10ms or 15ms. It's not a good method to call for timing; it's more appropriate for getting the current time.
To measure how long something takes, consider using System.nanoTime instead. The important point here isn't that the precision is greater, but that the resolution will be greater... but only when used to measure the time between two calls. It must not be used as a "wall clock".
Note that even System.nanoTime just uses "the most accurate timer on your system" - it's worth measuring how fine-grained that is. You can do that like this:
public class Test {
public static void main(String[] args) throws Exception {
long[] differences = new long[5];
long previous = System.nanoTime();
for (int i = 0; i < 5; i++) {
long current;
while ((current = System.nanoTime()) == previous) {
// Do nothing...
}
differences[i] = current - previous;
previous = current;
}
for (long difference : differences) {
System.out.println(difference);
}
}
}
On my machine that shows differences of about 466 nanoseconds... so I can't possibly expect to measure the time taken for something quicker than that. (And other times may well be roughly multiples of that amount of time.)
Since Java 1.5, you can get a more precise time value with System.nanoTime(), which obviously returns nanoseconds instead.
There is probably some caching going on in the instances when you get an immediate result.
From Java 8 onward you can try the following:
import java.time.*;
import java.time.temporal.ChronoUnit;
Instant start_time = Instant.now();
// Your code
Instant stop_time = Instant.now();
System.out.println(Duration.between(start_time, stop_time).toMillis());
//or
System.out.println(ChronoUnit.MILLIS.between(start_time, stop_time));
I do not know how does your PersonalizationGeoLocationServiceClientHelper works. Probably it performs some sort of caching, so requests for the same IP address may return extremely fast.
In the old days (you know, anytime before yesterday) a PC's BIOS timer would "tick" at a certain interval. That interval would be on the order of 12 milliseconds. Thus, it's quite easy to perform two consecutive calls to get the time and have them return a difference of zero. This only means that the timer didn't "tick" between your two calls. Try getting the time in a loop and displaying the values to the console. If your PC and display are fast enough, you'll see that time jumps, making it look as though it's quantized! (Einstein would be upset!) Newer PCs also have a high resolution timer. I'd imagine that nanoTime() uses the high resolution timer.
In such a small cases where difference is less than 0 milliseconds you can get difference in nano seconds as well.
System.nanoTime()
You can use
System.nanoTime();
To get the result in readable format, use
TimeUnit.MILLISECONDS or NANOSECONDS

Determining amount of time (in fractions (however small)) of a second in java (on finding solution)?

I have a program that will throw a simple exception when it's completed, when that exception is thrown is there any way to treat it like a stop-watch and stop the timer and display how long it took to solve the problem given?
Thanks a lot!
Milliseconds
System.currentTimeMillis() is a function that returns the current time in milliseconds. You can get invoke this function once when you start, and again when finished, then find the difference to determine the amount of time elapsed.
For example:
public void foo() {
long startTime = System.currentTimeMillis();
try {
doStuff();
} catch (Exception e) {
long endTime = System.currentTimeMillis();
long elapsedTime = endTime - startTime;
System.out.println("This operation took " + elapsedTime + " milliseconds.");
}
}
Nanoseconds
You can also use System.nanoTime() which is precise to nanosecond (rather than to the millisecond), but it is more limited in how much of a difference it can portray.
In the simplest case, use System.currentTimeMillis() to record the start and stop times (subtracting start from stop in the catch block). There are more complicated approaches with pretty interfaces. See, for example:
Stopwatch class for Java
Just be sure that the timer is in scope whenever the exception is caught.
Exception handling is an especially poor method of flow control - much better to break out of a loop, set the loop conditional to false, or return out of your recursive method.
For your actual question, you can get the system time with System.currentTimeMillis() at the start of your program, and then again at the end, and compare. Note that the system call is only accurate to 15ms, so this is only really useful for long running programs.

Java: What is the unit of the difference of two System.currentTimeMillis?

What is the unit of the difference of two System.currentTimeMillis ?
start = System.currentTimeMillis();
longoperation();
elapsedTime = System.currentTimeMillis() - start;
What is the unit of elapsed time here. It doesn't look like milliseconds.
Is the above code segment the right way to find the time taken to execute longoperation()?
Yes, it is in milliseconds. Bear in mind that the difference is not absolutely correct and may vary.
It is ms (MiliSecond) only, you are doing right.
You can ignore time taken while calculating millis
It is milliseconds and your code looks correct.
Whatever you are doing is correct. If you want the time in seconds, simply divide it by 1000.
long start = System.currentTimeMillis();
longoperation();
long elapsedTime = (System.currentTimeMillis() - start)/1000;
Yes, currentTimeMillis() returns you a milliseconds value.
On Windows, it used to be the case that the returned value had quite low resolution, and so was only accurate to something like 10ms. I'm not certain whether this is still the case as I haven't used Windows for a few years - but if your longoperation() actually takes just a few millis, and you're running on Windows, then you may see elapsedTime variously being 10ms or 0ms.

How can i benchmark method execution time in java?

I have a program which i have myself written in java, but I want to test method execution times and get timings for specific methods. I was wondering if this is possible, by maybe somehow an eclipse plug-in? or maybe inserting some code?
I see, it is quite a small program, nothing more than 1500 lines, which would be better a dedicated tool or System.currentTimeMillis()?
Other than using a profiler, a simple way of getting what you want is the following:
public class SomeClass{
public void somePublicMethod()
{
long startTime = System.currentTimeMillis();
someMethodWhichYouWantToProfile();
long endTime = System.currentTimeMillis();
System.out.println("Total execution time: " + (endTime-startTime) + "ms");
}
}
If the bottleneck is big enough to be observed with a profiler, use a profiler.
If you need more accuracy, the best way of measuring an small piece of code is the use of a Java microbenchmark framework like OpenJDK's JMH or Google's Caliper. I believe they are as simple to use as JUnit and not only you will get more accurate results, but you will gain the expertise from the community to do it right.
Follows a JMH microbenchmark to measure the execution time of Math.log():
private double x = Math.PI;
#Benchmark
public void myBenchmark() {
return Math.log(x)
}
Using the currentMillis() and nanoTime() for measuring has many limitations:
They have latency (they also take time to execute) which bias your measurements.
They have VERY limited precision, this means you can mesure things from 26ns to 26ns in linux and 300 or so in Windows has described here
The warmup phase is not taken into consideration, making your measurements fluctuate A LOT.
The currentMillis() and nanoTime() methods in Java can be useful but must be used with EXTREME CAUTION or you can get wrong measurements errors like this where the order of the measured snippets influence the measurements or like this where the author wrongly conclude that several millions of operations where performed in less than a ms, when in fact the JMV realised no operations where made and hoisted the code, running no code at all.
Here is a wonderful video explaining how to microbenchmark the right way: https://shipilev.net/#benchmarking
For quick and dirty time measurement tests, don't use wall-clock time (System.currentTimeMillis()). Prefer System.nanoTime() instead:
public static void main(String... ignored) throws InterruptedException {
final long then = System.nanoTime();
TimeUnit.SECONDS.sleep(1);
final long millis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - then);
System.out.println("Slept for (ms): " + millis); // = something around 1000.
}
You should use a profiler like
jprofiler
yourkit
They will easily integrate with any IDE and show whatever detail you need.
Of course these tools are complex and meant to be used to profile complex programs, if you need just some simple benchmarks I suggest you to use System.currentTimeMillis() or System.nanoTime() and calculate delta of millisecs between calls by yourself.
Using a profiler is better because you can find out average execution times and bottlenecks in your app.
I use VisualVM. slick and simple.
Google Guava has a stopwatch, makes things simple and easy.
Stopwatch stopwatch = Stopwatch.createStarted();
myFunctionCall();
LOGGER.debug("Time taken by myFunctionCall: " + stopwatch.stop());
Jprofiler and yourkit are good, but cost money.
There is a free plugin for eclispe called TPTP (Test & Performance Tools Platform) That can give you code execution times. Here is a tutorial that a quick google search brought up. http://www.eclipse.org/articles/Article-TPTP-Profiling-Tool/tptpProfilingArticle.html
Another Custom made solution could be based on the the following post : http://www.mkyong.com/spring/spring-aop-examples-advice/
You then have also the possibility to use the utilities around application monitoring & snmp. If you need to "time" your methods on a regular basis in a production environment, you proabably should consider using one of the those SNMP tools
Usually I store the time in a .txt file for analise the outcome
StopWatch sWatch = new StopWatch();
sWatch.start();
//do stuff that you want to measure
downloadContent();
sWatch.stop();
//make the time pretty
long timeInMilliseconds = sWatch.getTime();
long hours = TimeUnit.MILLISECONDS.toHours(timeInMilliseconds);
long minutes = TimeUnit.MILLISECONDS.toMinutes(timeInMilliseconds - TimeUnit.HOURS.toMillis(hours));
long seconds = TimeUnit.MILLISECONDS.toSeconds(timeInMilliseconds - TimeUnit.HOURS.toMillis(hours) - TimeUnit.MINUTES.toMillis(minutes));
long milliseconds = timeInMilliseconds - TimeUnit.HOURS.toMillis(hours) - TimeUnit.MINUTES.toMillis(minutes) - TimeUnit.SECONDS.toMillis(seconds);
String t = String.format("%02d:%02d:%02d:%d", hours, minutes, seconds, milliseconds);
//each line to store in a txt file, new line
String content = "Ref: " + ref + " - " + t + "\r\n";
//you may want wrap this section with a try catch
File file = new File("C:\\time_log.txt");
FileWriter fw = new FileWriter(file.getAbsoluteFile(), true); //append content set to true, so it does not overwrite existing data
BufferedWriter bw = new BufferedWriter(fw);
bw.write(content);
bw.close();
You can add this code and it will tell you how long the method took to execute.
long millisecondsStart = System.currentTimeMillis();
executeMethod();
long timeSpentInMilliseconds = System.currentTimeMillis() - millisecondsStart;

Categories

Resources