I was wondering if calculating a method's execution time this way is accurate:
public class GetExecutionTimes {
public static void main(String args[]) {
long startTime = System.currentTimeMillis();
GetExecutionTimes ext = new GetExecutionTimes();
ext.callMethod();
long endTime = System.currentTimeMillis();
System.out.println("Total elapsed time in execution of"
+ " method callMethod() is :" + (endTime - startTime));
}
public void callMethod() {
System.out.println("Calling method");
for (int i = 1; i <= 10; i++) {
System.out.println("Value of counter is " + i);
}
}
}
More specifically: Will the time difference be the same if I execute in different conditions?
If not how can I make this calculate more precise?
There are several aspects of Java that make writing micro-benchmarks difficult. Garbage collection and just-in-time compilation are two of them.
I would suggest the following as a very good starting point: How do I write a correct micro-benchmark in Java?
If you attempt to time only the method callMethod() you should move the constructor call before registering the start time.
You should also use nanoTime() rather then currentTimeMillis() since the letter is susceptible to errors due to changes in local clock (e.g. daylight saving time adjustments or someone on the machine simply changing the time).
The accuracy will depend on your platform and is not necessarily in the units the function names suggest.
Related
I have made a Java program similar to the code below :
class class1{
public static void main(String []args){
for(int i=0;i<100;i++){
class2 c2 = new class2();
c2.start();
}
}
}
class class2 extends Thread{
public void run(){
// do some long job here
}
}
This program uses threads which runs for significant amount of time. I want to analyze the time taken and memory consumed by the program in order to further optimize it. But the classical approach to calculate time like this one does not do the required job :
long startTime = System.currentTimeMillis();
doReallyLongThing();
long endTime = System.currentTimeMillis();
System.out.println("Time taken : " + (endTime - startTime) + " milliseconds");
Because the class1 finishes the job before the threads finish their jobs. So I want a command line solution to get the execution time. Something like using flags as command line arguments. Also the same for memory calculation. I found that jconsole command is helpful to analyze various aspects of java program but it opens in separate terminal and is not so good for the purpose I am looking for.
In our code, we often check arguments with Preconditions:
Preconditions.checkArgument(expression, "1" + var + "3");
But sometimes, this code is called very often. Could this have a notable negative impact on performance? Should we switch to
Preconditions.checkArgument(expression, "%s%s%s", 1, var, 3);
?
(i expect the condition true most of the time. False means bug.)
If you expect the check to not throw any exception most of the time, there is no reason to use the string concatenation. You'll lose more time concatenating (using .concat or a StringBuilder) before calling the method than doing it after you're sure you're throwing an exception.
Reversely, if you're throwing an exception, you're already in the slow branch.
It's also noteworthy to mention that Guava uses a custom and faster formatter which accepts only %s. So the loss of time is actually more similar to the standard logger {} handle (in slf4j or log4j 2). But as written above, this is in the case you're already in the slow branch.
In any case, I would strongly recommend against any of your suggestion, but I'd use this one instead:
Preconditions.checkArgument(expression, "1%s3", var);
You should only put variables in %s, not constants to gain marginal speed.
In the case of String literal concatenation, the compiler should do this in compilation time, so no runtime performance hit will occur. At least the standard JDK does this, it is not per specification (so some compilers may not optimize this).
In the case of variables, constant folding won't work, so there will be work in runtime. However, newer Java compilers will replace string concatenation to StringBuilder, which should be more efficient, as it is not immutable, unlike String.
This should be faster than using a formatter, if it is called. However, if you don't except it to be called very often, then this can be slower, as the concatenation always happen, even if the argument is true, and the method does nothing.
Anyway, to wrap it up: I do not think that it is worth to rewrite the existing calls. However, in new code, you can use the formatter without doubts.
I wrote a simple test. Using formatter is much faster as suggested here. The difference in performance grows with the number of calls (performance with formatter does not change O(1)). I guess the garbage collector time grows with number of calls in case of using simple strings.
Here is one sample result:
started with 10000000 calls and 100 runs
formatter: 0.94 (mean per run)
string: 181.11 (mean per run)
Formatter is 192.67021 times faster. (this difference grows with number of calls)
Here is the code (Java 8, Guava 18):
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
public class App {
public static void main(String[] args) {
int count = 10000000;
int runs = 100;
System.out.println("started with " + count + " calls and " + runs + "runs");
Stopwatch stopwatch = Stopwatch.createStarted();
run(count, runs, i->fast(i));
stopwatch.stop();
float fastTime = (float)stopwatch.elapsed(TimeUnit.MILLISECONDS)/ runs;
System.out.println("fast: " + fastTime + " (mean per run)");
//
stopwatch.reset();
System.out.println("reseted: "+stopwatch.elapsed(TimeUnit.MILLISECONDS));
stopwatch.start();
run(count, runs, i->slow(i));
stopwatch.stop();
float slowTime = (float)stopwatch.elapsed(TimeUnit.MILLISECONDS)/ runs;
System.out.println("slow: " + slowTime + " (mean per run)");
float times = slowTime/fastTime;
System.out.println("Formatter is " + times + " times faster." );
}
private static void run(int count, int runs, Consumer<Integer> function) {
for(int c=0;c<count;c++){
for(int r=0;r<runs;r++){
function.accept(r);
}
}
}
private static void slow(int i) {
Preconditions.checkArgument(true, "var was " + i);
}
private static void fast(int i) {
Preconditions.checkArgument(true, "var was %s", i);
}
}
I am looking for a way to interrupt a loop in Java without multithreading.
public class Foo{
public Foo(){
}
public void bar(long timeLimit) {
long endTime = System.currentTimeMillis() + (timeLimit * 1000);
while (System.currentTimeMillis() < endTime) {
// Some really long and complicated computation
}
}
}
At the moment I realized that which various (System.currentTimeMillis() < timeLimit) calls to check during the computation if there is time left but I guess that eats up some time and I am also facing the problem that if a loop starts in time, the computation might not be done in time.
Amending the timeLimit (let's say only using 40 % of the time) accordingly also does not work, because I cannot predict how long some computations take.
Which options are there?
So I have started using System.currentTimeMillis(); I am trying to test the results between two of my methods. I decided to gut my method so that what it does doesn't get in the way. Basically I am not seeing any change in time. I have something like this:
double start= System.currentTimeMillis();
double end=System.currentTimeMillis();
public void displayMethod()
{
System.out.println("The start time is" + start);
for (ITERATIONS AND STUFF)
{
System.out.format(STUFF BEING PRINTED);
}
System.out.println("The end time is" + end);
double difference = start-end;
System.out.println("The difference " + difference);
}
The idea is that I have a start time, the time between every print out of the statement and the time at the end. Then it is subtracted to show the difference. However there is no difference and all the times are the same. Why is this happening?
I am considering using nanotime but I don't really know how to use that and I have heard that it takes performance hits.
Can anyone tell me why my times are the same and suggest a way to
fix it or give me an alternative route that is suitable gets the
answer?
You're capturing all of the times at the beginning with these lines:
double thetime= System.currentTimeMillis();
double start= System.currentTimeMillis();
double end=System.currentTimeMillis();
You're getting the same times because those lines are executed immediately back to back (and are fast calls so likely happen in less than 1ms)
Adjust your code to:
public void displayMethod()
{
long start= System.currentTimeMillis();
System.out.println("The start time is" + start);
for (ITERATIONS AND STUFF)
{
System.out.format(STUFF BEING PRINTED);
System.out.println(System.currentTimeMillis());
}
long end=System.currentTimeMillis();
System.out.println("The end time is" + end);
double difference = end-start;
System.out.println("The difference " + difference);
}
Notice how the declarations of the variables are moved to the places that they are needed. It's important to note that variable assignment happens at declaration time not at usage time, thus it's important to move the calls to System.currentTimeMillis() to the point at which you want to capture the current time.
Side note: I adjusted the variables to long instead of double, as System.currentTimeMillis() returns a long and there's no reason for a double here.
You are getting all the times at the very beginning. You need to call System.currentTimeMillis() in the place that you want to know the time.
you should call currentTimeMillis minus the start time, where you want to find the total time ran.
This question already has answers here:
How do I time a method's execution in Java?
(42 answers)
Closed 9 years ago.
How do I calculate the time taken for the execution of a method in Java?
To be more precise, I would use nanoTime() method rather than currentTimeMillis():
long startTime = System.nanoTime();
myCall();
long stopTime = System.nanoTime();
System.out.println(stopTime - startTime);
In Java 8 (output format is ISO-8601):
Instant start = Instant.now();
Thread.sleep(63553);
Instant end = Instant.now();
System.out.println(Duration.between(start, end)); // prints PT1M3.553S
Guava Stopwatch:
Stopwatch stopwatch = Stopwatch.createStarted();
myCall();
stopwatch.stop(); // optional
System.out.println("Time elapsed: "+ stopwatch.elapsed(TimeUnit.MILLISECONDS));
You can take timestamp snapshots before and after, then repeat the experiments several times to average to results. There are also profilers that can do this for you.
From "Java Platform Performance: Strategies and Tactics" book:
With System.currentTimeMillis()
class TimeTest1 {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
long total = 0;
for (int i = 0; i < 10000000; i++) {
total += i;
}
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
System.out.println(elapsedTime);
}
}
With a StopWatch class
You can use this StopWatch class, and call start() and stop before and after the method.
class TimeTest2 {
public static void main(String[] args) {
Stopwatch timer = new Stopwatch().start();
long total = 0;
for (int i = 0; i < 10000000; i++) {
total += i;
}
timer.stop();
System.out.println(timer.getElapsedTime());
}
}
See here (archived).
NetBeans Profiler:
Application Performance Application
Performance profiles method-level CPU
performance (execution time). You can
choose to profile the entire
application or a part of the
application.
See here.
Check this: System.currentTimeMillis.
With this you can calculate the time of your method by doing:
long start = System.currentTimeMillis();
class.method();
long time = System.currentTimeMillis() - start;
In case you develop applications for Android you should try out the TimingLogger class.
Take a look at these articles describing the usage of the TimingLogger helper class:
Measuring performance in the Android SDK (27.09.2010)
Discovering the Android API - Part 1 (03.01.2017)
You might want to think about aspect-oriented programming. You don't want to litter your code with timings. You want to be able to turn them off and on declaratively.
If you use Spring, take a look at their MethodInterceptor class.
If you are currently writing the application, than the answer is to use System.currentTimeMillis or System.nanoTime serve the purpose as pointed by people above.
But if you have already written the code, and you don't want to change it its better to use Spring's method interceptors. So for instance your service is :
public class MyService {
public void doSomething() {
for (int i = 1; i < 10000; i++) {
System.out.println("i=" + i);
}
}
}
To avoid changing the service, you can write your own method interceptor:
public class ServiceMethodInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = methodInvocation.proceed();
long duration = System.currentTimeMillis() - startTime;
Method method = methodInvocation.getMethod();
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
System.out.println("Method '" + methodName + "' took " + duration + " milliseconds to run");
return null;
}
}
Also there are open source APIs available for Java, e.g. BTrace.
or Netbeans profiler as suggested above by #bakkal and #Saikikos.
Thanks.
As proposed nanoTime () is very precise on short time scales.
When this precision is required you need to take care about what you really measure.
Especially not to measure the nanotime call itself
long start1 = System.nanoTime();
// maybe add here a call to a return to remove call up time, too.
// Avoid optimization
long start2 = System.nanoTime();
myCall();
long stop = System.nanoTime();
long diff = stop - 2*start2 + start1;
System.out.println(diff + " ns");
By the way, you will measure different values for the same call due to
other load on your computer (background, network, mouse movement, interrupts, task switching, threads)
cache fillings (cold, warm)
jit compiling (no optimization, performance hit due to running the compiler, performance boost due to compiler (but sometimes code with jit is slower than without!))
Nanotime is in fact not even good for elapsed time because it drifts away signficantly more than currentTimeMillis. Furthermore nanotime tends to provide excessive precision at the expense of accuracy. It is therefore highly inconsistent,and needs refinement.
For any time measuring process,currentTimeMillis (though almost as bad), does better in terms of balancing accuracy and precision.