Skip to main content

Thread.Sleep(1) problem

7 replies [Last post]
mconti
Offline
Joined: 2010-11-28
Points: 0

Hello,
I'm new to java, embedded linux and PhoneME (mr2).
I'm trying to run the following code:
package TestSleep;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class Main
{
public static void main(String[] args)
{
long ts, te;
while(true)
{
try
{
ts=System.currentTimeMillis();
Thread.sleep(1);
te=System.currentTimeMillis();
System.out.println("main - Thread.sleep(1) - took: " + (te-ts) + " ms");
}
catch (InterruptedException ex)
{
System.out.println(ex.getMessage());
}
}
}
}
In the x86 the result is 1 ms.
In the ARM9 the result is not 1 ms !!!
Here the result is 7 ms, 8 ms or so.

Can somebody help me to solve the problem ?

Thanks.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
cjplummer
Offline
Joined: 2006-10-16
Points: 0

Why do you consider this a problem that needs to be solved? The JavaDocs for Threads.sleep() say "causes the current thread to sleep for the specified number of milliseconds, subject to the precision and accuracy of the system timers and schedulers". Different platforms run at different speeds and can also have different thread scheduling characteristics. Most thread packages are going to implement sleep by setting suspending the thread, and then rescheduling it after a 1ms timer goes off. However, just because it gets rescheduled does not mean it will run right away, and you area also dealing with the accuracy of the timer.

mconti
Offline
Joined: 2010-11-28
Points: 0

Dear cjplummer,

Thank you for your replay, and also thanks to point me to the JavaDocs for Threads.sleep().

sleep(long millis)
Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers.
There are two reasons why i consider this is a problem.
The first is because, like it says, i expect it to sleep 1 ms, and it doesn't. (so the guilty seems to be linux for ARM ? How can i tweak it to get Threads.sleep(1) sleeps only for 1 ms and not 7 or 8 ms?). The second is because in a thread i have a loop and i need to let sleep it for 1 ms, in order to avoid consuming the CPU usage.
1 ms of sleep time, is also useful to the logic of the loop in the thread, that needs to wait that time, before going to check for inbound or outbound network buffer communication.
When the sleep time is 1 ms (x86), the performance is fine.
When the sleep time is 7 or 8 ms (ARM9) instead of 1ms, the performance is poor.
I hope now you understand why i consider it a problem and also hope you can drive me to the solution, by solving it to the root of the problem.
Thanks again.

cjplummer
Offline
Joined: 2006-10-16
Points: 0

You are expecting more out of sleep() then it is spec'd to do. I don't know details about how quickly a typical ARM9 linux platform handles the thread sleep->wake-up cycle, but you are likely comparing a 200Mhz ARM core with a 2-3Ghz x86 desktop, so that alone could explain why it is taking much longer.
You might want to try playing with thread priorities. Making the thread that is sleeping the highest priority and the one with periodic tasks the lowest might help. Otherwise you need to restructure your program so you don't need to rely on sleep to get the periodic tasks done.
Another thing to try is sleep(0). That suspends the thread, but puts it immediately back on the the reschedule queue rather than waiting for a 1ms timer to go off. It should allow some time for your other thread before switching back to the thread that called sleep(0).

mconti
Offline
Joined: 2010-11-28
Points: 0

Dear cjplummer,
Thanks for your reply.
I understand what you say about comparing a 200Mhz ARM core with a 2-3Ghz x86 desktop, but i don't completly agree with you.
From the Thread.Sleep() command i expected what it is supposed to do. There is also another version of the sleep (from javaDoc):
sleep(long millis, int nanos)
Causes the currently executing thread to sleep (cease execution) for the specified number of milliseconds plus the specified number of nanoseconds, subject to the precision and accuracy of system timers and schedulers.
Even nano seconds !!! I think these are for real time OS!
I found an article here about the sleep:
http://www.javamex.com/tutorials/threads/sleep.shtml
So the matter should be the resolution of sleep under linux for ARM9.
According to that article the resolution of sleep under linux should be 1ms.
I need to know the minimal resolution for linux ARM9 or if it could be improved.
I think it can, but i'm not an expert.
The test program i posted above is not complicated and doesn't require CPU calculation time or power.
It is all about sleep time.
Thanks for the thrad priority tip.
Thanks also for the sleep(0) tip, it make sense.
I will give it a try and let you know, but i feel i'll get the same result because 7-8 ms seems to be the minimal resolution.
Thanks a lot for your help.

cjplummer
Offline
Joined: 2006-10-16
Points: 0

You say "From the Thread.Sleep() command i expected what it is supposed to do" but you keep ignoring that it is "subject to the precision and accuracy of system timers and schedulers", so it is doing what it is suppose to do. If you want guaranteed precission from Thread.sleep(), you would need a realtime OS and probalby realtime java too.
A collegue suggested to me that you try java.util.Timer/TimerTask for scheduling periodic task. This way you don't need to call sleep, and the main thread will instead be interrupted when the timer goes off.

mconti
Offline
Joined: 2010-11-28
Points: 0

Dear cjplummer,
OK, we agree.
The guilty seems to be the "precision and accuracy of system timers and schedulers" in the linux for ARM9,
but as a matter of fact, Thread.Sleep(1) doesn't sleep 1 ms. I didn't say the guilty is the Java Thread.Sleep().
I said Thread.Sleep(1) doesn't sleep 1 ms and i expect it to do so, also because i relay on it.
I never had problem with it in VB6 or C# (x86).

In the example i posted above, i tryed to use Thread.Sleep(0) and the output is 0 or 1 ms. This is interesting, but the problem now is that it consumes the CPU,
so actually it dosen't release the CPU usage and it doesn't do what it is expected to do ;-)
Thank you for helping me and for the suggestion of the use java.util.Timer/TimerTask.

Thanks a lot for your help.

mconti
Offline
Joined: 2010-11-28
Points: 0

To close this post I would like to report a workaround I discovered.

To get the behavior of Thread.Sleep(1), as it is expected to do i did the following:

1) In the loop i use Thread.Sleep(0), instead of Thread.Sleep(1).
2) To avoid consuming the CPU I used a counter in the loop that every 100 cycles let does Thread.Sleep(1) instead of Thread.Sleep(0).

The performance is good (the same i get in the x86) and the CPU usage is 0%.

My thanks goes to cjplummer.