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.
Related
for(i=1;i<list.size();i++){
//do something
//For Eg: move marker to a new position on the map
}
I want the above loop to complete all the iterations irrespective of the size of the list and also want the entire task to run for 1 minute. (60 seconds)
I don't really know if this is what you want but I hope this helps.
import java.util.concurrent.TimeUnit;
for(i=1;i<list.size();i++){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Execute thing you want to be executed every second
}
As explanation: you iterate through the for loop and the thread waits for one second before executing the code after the TimeUnit.SECONDS.sleep(1);.
If the list's size is 60 it would therefore take a minute for the loop to end.
Edit: It has occurred to me that it might be smarter to do a try-catch around the sleep function.
You can, for example, use System.nanoTime() to measure the duration of your loop, and then use TimeUnit.NANOSECONDS.sleep(...) to make it wait for the rest of time like this:
long start = System.nanoTime();
long desiredDuration = 60 * 1000 * 1000;
// your loop goes here
long duration = System.nanoTime() - start;
if (duration < desiredDuration)
TimeUnit.NANOSECONDS.sleep(desiredDuration - duration);
The best possible solution is to compute the desired time first and then run the loop to that extent.
long finish=System.currentTimeMillis() + 60000;
while(System.currentTimeMillis() != finish)
{
//statements;
//statements;
}
If you are trying to equip the CPU and keep it idle for this time the process is known as busy waiting but is not considered convenient in many cases so i recommend to use Thread.sleep(duration) for this purpose.
Would like to receive further queries from your side.
To spread N amount of invocations uniformly across a minute, you'll have to set the delay in between the invocations to the value 60/(N-1). The -1 is optional but causes the first and last invocations to be exactly 60 seconds apart. (just like how a ladder with N rungs has N-1 spaces)
Of course, using sleep() with the number calculated above is not only subject to round-off errors, but also drift, because you do stuff between the delays, and that stuff also takes time.
A more accurate solution is to subtract the time at which each invocation should occur (defined by startTime + 60*i/(N-1)) from the current time. Reorder and reformulate those formulas and you can subtract the 'time that should have elapsed for the next invocation' from the already elapsed time.
Of course 'elapsed time' should be calculated using System.nanoTime() and not System.currentTimeMillis() as the latter can jump when the clock changes or the computer resumes from stand-by.
For this example I changed 60 seconds to 6 seconds so you can more easily see what's going on when you run it.
public static void main(String... args) throws Exception {
int duration = 6; // seconds
List<Double> list = IntStream.range(0, 10).mapToDouble(i->ThreadLocalRandom.current().nextDouble()).boxed().collect(Collectors.toList());
long startTime = System.nanoTime();
long elapsed = 0;
for (int i = 0; i < list.size(); i++) { // Bug fixed: start at 0, not at 1.
if (i > 0) {
long nextInvocation = TimeUnit.NANOSECONDS.convert(duration, TimeUnit.SECONDS) * i / (list.size() - 1);
long sleepAmount = nextInvocation - elapsed;
TimeUnit.NANOSECONDS.sleep(sleepAmount);
}
elapsed = System.nanoTime() - startTime;
doSomething(elapsed, list.get(i));
}
}
private static void doSomething(long elapsedNanos, Double d) {
System.out.println(elapsedNanos / 1.0e9f + "\t" + d);
}
Of course when the task you preform per list element takes longer than 60/(N-1) seconds, you get contention and the 'elapsed time' deadlines are always exceeded. With this algorithm the total time just taking longer than a mnute. However if some earlier invocations exceed the deadline, and later invocations take much less time than 60/(N-1), this algorithm will show 'catch-up' behavior. This can be partially solved by sleeping at least a minimum amount even when sleepAmount is less.
Check out this.
long start = System.currentTimeMillis();
long end = start + 60*1000; // 60 seconds * 1000 ms/sec
int i = 0;
while (System.currentTimeMillis() < end)
{
// do something, iterate your list
i++;
if (i == list.size()) { // check size of the list if iteration is completed
// if time has not yet expired, sleep for the rest of the time
Thread.sleep(end - System.currentTimeMillis());
}
}
Do not forget checking size of the list.
The following Java method is meant to print the number i by nLoopsPerSecond times per second for seconds seconds:
public void test(int nLoopsPerSecond, int seconds) {
double secondsPerLoop = 1.0/(double)nLoopsPerSecond;
long startTime = System.currentTimeMillis();
long currentTime;
int i = 0;
while ((currentTime = System.currentTimeMillis()) < startTime + seconds*1000) {
System.out.println(i++);
while (System.currentTimeMillis() < currentTime + secondsPerLoop*1000);
}
}
With the following call:
test(1000,1);
I expect this method to do the System.out.println(i++); 1,000 times, but I only got 63.
When I try to see how many seconds it actually use per loop with this code
public void test(int nLoopsPerSecond, int seconds) {
double secondsPerLoop = 1.0/(double)nLoopsPerSecond;
long startTime = System.currentTimeMillis();
long currentTime;
int i = 0;
while ((currentTime = System.currentTimeMillis()) < startTime + seconds*1000) {
while (System.currentTimeMillis() < currentTime + secondsPerLoop*1000);
System.out.println(System.currentTimeMillis() - currentTime);
}
}
I expect it to print 1 milliseconds each loop, but it prints 15 or 16 milliseconds.
Please suggest what is wrong in my code.
Are you running on Windows, perhaps? System.currentTimeMillis() consults the underlying operating system clock, which is only 60Hz on many versions of Windows.
Try System.nanoTime() since you are not measuring time since the epoch. System.currentTimeMillis vs System.nanoTime
That's probably because the processing takes up some time. The processor does not solely dedicate its time to the execution of your program, it performs several other functions in the background. So you might get different results based on the processor load.
Your output console is not fast enough. You do not mention how you run your test and where the output goes. The speed of the terminal and buffers (not) used will limit how fast can the program output data. If running unbuffered, your program will always have to wait, until the new line is printed on screen. If the console waits for screen redraw and screen is redrawn at 60Hz, you've got your 16ms/line and about 60 lines per second.
Running your code without inner loop inside IntelliJ Idea, I get about 140.000 lines per second (and Idea warns me, that it is not displaying every line, as my output is too fast).
With the inner loop, I get about 800-900 lines. That happens because the process may be scheduled out of cpu, or blocked because of something else, like swapping. (If I simplify a lot, usually desktop OSes schedule in 1ms granularity.)
My program runs 30000ns faster with this code:
long t = System.nanoTime();
...
long t2 = System.nanoTime();
System.out.println("Time: " + (t2 - t));
Than with this other:
long t = System.nanoTime();
...
System.out.println("Time: " + (System.nanoTime() - t));
In the first one, I even make another variable, why is it faster then?
The second one creates a new StringBuilder and appends a String to it before taking the timings. The first one takes the timing before doing this extra work.
The second one is equivalent to
System.out.println(new StringBuilder().append("Time: ")
.append(System.nanoTime() - t).toString());
or
StringBuildler sb = new StringBuilder().append("Time: "); // included in timing
long time = System.nanoTime() - t;
System.out.println(sb.append(time).toString());
BTW Just performing an output to the console can disturb very short tasks and make them slower. I suggest you run the test many times, ignore the first 20K as warm up and print a summary of the results at the end.
I keep getting a lot of "Delta: 0.0"s in my console and ever few lines I get something like "Delta: 9.999275207519531E-4", what's happening?
Timer timer = new Timer();
float lastTime = 0.0f;
timer.resume();
while (!Display.isCloseRequested())
{
timer.tick();
System.out.println("Delta: " + (timer.getTime() - lastTime));
lastTime = timer.getTime();
Display.update();
}
Display.destroy();
Don't ever use java's Timer class in your game loops. It isn't precise enough to use reliably. Instead, check out this link to see a couple of reliable game loops written in java.
One little note, just a warning. Your timing mechanism is flawed a bit.
Considering this code runs line by line as it is written, you'll "loose" time. This
System.out.println("Delta: " + (timer.getTime() - lastTime));
lastTime = timer.getTime();
code does the following:
1. Getting current time.
2. Doing some math.
3. Calling String constructor.
4. Performing String concatenation.
5. Writing current time to the lastTime variable.
Note that current time in the 1 and 5 cases are different. That means that this time is "lost" from the "Delay: xx" output.
If you continue to use (timer.getTime() - lastTime) technics in your code for the purpose of getting time passed from the previous iteration, you will surely run into problem where different events thinks that time passed from the previous iteration is different. I recommend you to use the following code for timing:
private double delta;
private long timing;
public void updateTime()
{
long newTime = System.nanoTime();
this.delta = (newTime - this.timing) / 1_000_000_000.0;
this.timing = newTime;
}
public double getDelta() {
return this.delta;
}
where updateTime() is called once per cycle and getDelta() is called every time you want to get time passed from the previous iteration.
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.