How to improve the performance for System.currentTimeMillis();? - java

The System.currentTimeMillis(); is system method in Java.
If invoke this method serially, it seems that no performance issues.
But if you keep invoking this method concurrently, the performance issue will occurred explicitly. As the native method dependent with OS clock_source. But how to improve it performance in Java. Refresh time milli policy with fixed rate is not usable.
Examples like below:
int parallism = 32;
for(int i=0;i< parallism ;i++){
new Thread(() -> {
for(;;){
// Focus here, how can i measure the logic efficiently
long begin = System.currentTimeMillis();
// Here may be the logic:
// Define empty block here means 0ms elapsed
long elapsed = (System.currentTimeMillis() - begin);
if(elapsed >= 5){
System.err.println("Elapsed: "+elapsed+" ms.");
}
}
}).start();
}
Thread.sleep(Integer.MAX_VALUE); // Just avoid process exit

Reason of low performance: https://pzemtsov.github.io/2017/07/23/the-slow-currenttimemillis.html
(Unusable) Another solution: https://programmer.group/5e85bd0cc8b52.html
Wait me to post my solution....

Try to use
System.nanoTime() instead of System.currentTimeMills();

Related

java: I am supposed to call a method 50x per second in the run method of a thread, ONLY WITH THE METHOD SLEEP (All other threads here with timer)

I have to call a method in the run method of a thread 50 times in one second, the problem is, i am only allowed to use sleep as a method!
Now the problem is how can i do that, other threads here for instance:
java- Calling a function at every interval
do that with a timer.
With a timer its easy. But i am only allowed to use sleep as a method...
while (true) {
long t0 = System.currentTimeMillis();
doSomething();
long t1 = System.currentTimeMillis();
Thread.sleep(20 - (t1-t0));
}
t1 minus t0 is the time you spent in 'doSomething', so you need to sleep for that much less than 20 mS.
You probably ought to add some checks for t1-t0 > 20.
You cannot avoid jitter in timing based on System.currentTimeMillis() (or, based on any other system clock).
This solution will not accumulate error due to jitter (unlike another answer here that measures how long the task actually took on each iteration of the loop.) Use this version if it's important for the task to be performed exactly the right number of times over a long span of time.
long dueDate = System.currentTimeMillis();
while (true) {
performThePeriodicTask();
dueDate = dueDate + TASK_PERIOD;
long sleepInterval = dueDate - System.currentTimeMillis();
if (sleepInteval > 0) {
Thread.sleep(sleepInterval);
}
}

How to check threads timing?

I wrote an application which reads all lines in text files and measure times. I`m wondering what will be the time of whole block.
For example if I start 2 threads at the same time:
for (int i = 0; i < 2; i++) {
t[i] = new Threads(args[j], 2);
j++;
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("TIME for block 1 of threads; "
+ (max(new long[]{t[0].getTime(),t[1].getTime()})));
Wait for them to stop processing the files and read operation times (by getTime). Is it good thinking for multithreading that in this case the time of block of threads, will be the maximum time got from thread? I think yes, because other threads will stop working by the time the thread with max time will stop.
Or maybe should I think in another way?
It's dangerous to argue about execution order when having multiple threads! E.g. If you run your code on a single core CPU, the threads will not really run in parallel, but sequentially, so the total run time for both threads is the sum of each thread's run time, not the maximum of both.
Fortunately, there is a very easy way to just measure this if you use an ExecutorService instead of directly using Threads (btw. this is always a good advice):
// 1. init executor
int numberOfThreads = 2; // or any other number
int numberOfTasks = numberOfThreads; // is this true in your case?
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
long startTime = System.currentTimeMillis();
// 2. execute tasks in parallel using executor
for(int i = 0; i < numberOfTasks; i++) {
executor.execute(new Task()); // Task is your implementation of Runnable
}
// 3. initiate shutdown and wait until all tasks are finished
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES); // we won't wait forever
// 4. measure time
long delta = System.currentTimeMillis() - startTime;
Now, delta holds the total running time of your tasks. You can play around with numberOfThreads to see if more or less threads give different results.
Important note: Reading from a file is not thread-safe in Java, so it is not allowed to share a Reader or InputStream between threads!
As far as my concern You can Use System class's static methods.
You can use it in starting of the block and end of the block and subtract the later one with earlier time.
those are :
System.currentTimeMillis(); // The current value of the system timer, in miliseconds.
or
System.nanoTime(); //The current value of the system timer, in nanoseconds.
You can use
Starting of block
long startTime = System.currentTimeMillis();
End of block
long endTime = System.currentTimeMillis()- startTime;
By this you can calculate.

Wait for system time to continue application

I've written a class to continue a started JAVA application if the current second is a multiple of 5 (i.e. Calender.SECOND % 5 == 0)
The class code is presented below, what I'm curious about is, am I doing this the right way? It doesn't seem like an elegant solution, blocking the execution like this and getting the instance over and over.
public class Synchronizer{
private static Calendar c;
public static void timeInSync(){
do{
c = Calendar.getInstance();
}
while(c.get(Calendar.SECOND) % 5 != 0);
}
}
Synchronizer.timeInSync() is called in another class's constructor and an instance of that class is created at the start of the main method. Then the application runs forever with a TimerTask that's called every 5 seconds.
Is there a cleaner solution for synchronizing the time?
Update:
I think I did not clearly stated but what I'm looking for here is to synchronization with the system time without doing busy waiting.
So I need to be able to get
12:19:00
12:19:05
12:19:10
...
What you have now is called busy waiting (also sometimes referred as polling), and yes its inefficient in terms of processor usage and also in terms of energy usage. You code executes whenever the OS allows it, and in doing so it prevents the use of a CPU for other work, or when there is no other work it prevents the CPU from taking a nap, wasting energy (heating the CPU, draining the battery...).
What you should do is put your thread to sleep until the time where you want to do something arrives. This allows the CPU to perform other tasks or go to sleep.
There is a method on java.lang.Thread to do just that: Thread.sleep(long milliseconds) (it also has a cousin taking an additional nanos parameter, but the nanos may be ignored by the VM, and that kind of precision is rarely needed).
So first you determine when you need to do some work. Then you sleep until then. A naive implementation could look like that:
public static void waitUntil(long timestamp) {
long millis = timestamp - System.currentTimeMillis();
// return immediately if time is already in the past
if (millis <= 0)
return;
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
This works fine if you don't have too strict requirements on precisely hitting the time, you can expect it to return reasonably close to the specified time (a few ten ms away probably) if the time isn't too far in the future (a few secs tops). You have however no guarantees that occasionally when the OS is really busy that it possily returns much later.
A slightly more accurate method is to determine the reuired sleep time, sleep for half the time, evaluate required sleep again, sleep again half the time and so on until the required sleep time becomes very small, then busy wait the remaining few milliseconds.
However System.currentTimeMillis() does not guarantee the actual resolution of time; it may change once every millisecond, but it might as well only change every ten ms by 10 (this depends on the platform). Same goes for System.nanoTime().
Waiting for an exact point in time is not possible in high level programming languages in a multi-tasking environment (practically everywhere nowadays). If you have strict requirements, you need to turn to the operating system specifics to create an interrupt at the specified time and handle the event in the interrupt (that means assembler or at least C for the interrupt handler). You won't need that in most normal applications, a few ms +/- usually don't matter in a game/application.
As #ChrisK suggests, you could simplify by just making a direct call to System.currentTimeMillis().
For example:
long time = 0;
do
{
time = System.currentTimeMillis();
} while (time % 5000 != 0);
Note that you need to change the comparison value to 5000 because the representation of the time is in milliseconds.
Also, there are possible pitfalls to doing any comparison so directly like this, as the looping call depends on processor availability and whatnot, so there is a chance that an implementation such as this could make one call that returns:
`1411482384999`
And then the next call in the loop return
`1411482385001`
Meaning that your condition has been skipped by virtue of hardware availability.
If you want to use a built in scheduler, I suggest looking at the answer to a similar question here java: run a function after a specific number of seconds
You should use
System.nanoTime()
instead of
System.currentTimeMillis()
because it returns the measured elapsed time instead of the system time, so nanoTime is not influenced by system time changes.
public class Synchronizer
{
public static void timeInSync()
{
long lastNanoTime = System.nanoTime();
long nowTime = System.nanoTime();
while(nowTime/1000000 - lastNanoTime /1000000 < 5000 )
{
nowTime = System.nanoTime();
}
}
}
The first main point is that you must never use busy-waiting. In java you can avoid busy-waiting by using either Object.wait(timeout) or Thread.sleep(timeout). The later is more suitable for your case, because your case doesn't require losing monitor lock.
Next, you can use two approaches to wait until your time condition is satisfied. You can either precalculate your whole wait time or wait for small time intervals in loop, checking the condition.
I will illustrate both approaches here:
private static long nextWakeTime(long time) {
if (time / 1000 % 5 == 0) { // current time is multiple of five seconds
return time;
}
return (time / 1000 / 5 + 1) * 5000;
}
private static void waitUsingCalculatedTime() {
long currentTime = System.currentTimeMillis();
long wakeTime = nextWakeTime(currentTime);
while (currentTime < wakeTime) {
try {
System.out.printf("Current time: %d%n", currentTime);
System.out.printf("Wake time: %d%n", wakeTime);
System.out.printf("Waiting: %d ms%n", wakeTime - currentTime);
Thread.sleep(wakeTime - currentTime);
} catch (InterruptedException e) {
// ignore
}
currentTime = System.currentTimeMillis();
}
}
private static void waitUsingSmallTime() {
while (System.currentTimeMillis() / 1000 % 5 != 0) {
try {
System.out.printf("Current time: %d%n", System.currentTimeMillis());
Thread.sleep(100);
} catch (InterruptedException e) {
// ignore
}
}
}
As you can see, waiting for the precalculated time is more complex, but it is more precise and more efficient (since in general case it will be done in single iteration). Waiting iteratively for small time interval is simpler, but less efficient and precise (precision is dependent on the selected size of the time interval).
Also please note how I calculate if the time condition is satisfied:
(time / 1000 % 5 == 0)
In first step you need to calculate seconds and only then check if the are multiple of five. Checking by time % 5000 == 0 as suggested in other answer is wrong, as it is true only for the first millisecond of each fifth second.

Loop throttled with Thread.sleep() runs more than twice as often as intended

I use the following loop (cut some stuff out) as the main loop for a game, but I can't get it to throttle down to a speed I want it to, it keeps running about twice as fast as I intend.
private void myLoop() throws InterruptedException {
long timer = TimeUtils.getMillis();
int achievedLoops = 0;
long currTime = 0l;
long loopTime = 0l;
long lastTime = TimeUtils.getNano();
while(!isRequestedToStop) {
currTime = TimeUtils.getNano();
loopTime = currTime - lastTime;
lastTime = currTime;
if(TimeUtils.getDeltaMillis(timer) > 1000) {
timer += 1000;
logger.debug(achievedLoops + " Loops");
achievedLoops = 0;
}
achievedLoops++;
if(loopTime < TIME_PER_LOOP) {
Thread.sleep( (TIME_PER_LOOP - loopTime) / 1000000l);
}
}
}
Alternative implementation of the sleeping, gets slightly better results (loop runs only 1.9 times too often):
while(loopTime < TIME_PER_LOOP) {
Thread.sleep(1l);
loopTime += 1000000l;
}
Another alternative:
while(loopTime < TIME_PER_LOOP) {
Thread.sleep(1l);
loopTime = TimeUtils.getNano() - lastTime;
}
Why does that happen?
Are there any other ways to throttle a thread down?
I basically could run it uncontrolled as the logic is tied to timed steps, but I would like to reduce the total runs of the loop as otherwise there's a marginal chance of it doing damage to a CPU..
LockSupport can disable the scheduling of a thread for a specified number of nanoseconds.
LockSupport.parkNanos(TIME_PER_LOOP - loopTime);
But as others have mentioned there are better ways to control timing (e.g. ScheduledExecutorService).
Each time you perform the division
(TIME_PER_LOOP - loopTime) / 1000000l
You are truncating the result and sleeping up to 1ms less than you expect (average 0.5ms). Given your 4ms loop time, this would easily cause your loop to run twice as fast as you expect. As others have mentioned, there are much better ways to control timing.

Strange code timing behavior in Java

In the following code:
long startingTime = System.nanoTime();
int max = (int) Math.pow(2, 19);
for(int i = 0; i < max; ){
i++;
}
long timePass = System.nanoTime() - startingTime;
System.out.println("Time pass " + timePass / 1000000F);
I am trying to calculate how much time it take to perform simple actions on my machine.
All the calculations up to the power of 19 increase the time it takes to run this code, but when I went above 19(up to max int value 31) I was amazed to discover that it have no effect on the time it takes.
It always shows 5 milliseconds on my machine!!!
How can this be?
You have just witnessed HotSpot optimizing your entire loop to oblivion. It's smart. You need to do some real action inside the loop. I recommend introducing an int accumulator var and doing some bitwise operations on it, and finally printing the result to ensure it's needed after the loop.
On the HotSpot JVM, -XX:CompileThreshold=10000 by default. This means a loop which iterates 10K times can trigger the whole method to be optimised. In your case you are timing how long it take to detect and compile (in the background) your method.
use another System.nanoTime() in the loop. no one can optimize this.
for(int i = 0; i < max; ){
i++;
dummy+=System.nanoTime();
}
dont forget to do:
System.out.println(dummy);
after the loop. ensures non-optimization

Categories