1

A few days ago I posted this question: measuring time of a profiled function

(I hope it's ok i'm opening a new thread, I just can't find the old one in the few first pages)

I noticed that in my profiled process, I call a "Sleep" method - and this is the problem... When I call SuspendThread/ResumeThread - The Sleeping process pauses, but in reality - time moves on!
I figure that "Sleep" is just some kind of a loop that takes the time and stops whenever the difference between the start time and the end time is large enough.

well, suppose that your profiled process needs to sleep for 1 minute.
You suspended the profiled process after sleeping 2 seconds, and went to eat something.
You came back after 15 minutes and resumed the profiled process.
The profiled process measures the time, finds that MORE than 1 minute passed and it stops sleeping.

that's how I made the process sleep too little (time passes on, when the process is suspended, the Sleep takes it into account - but I can't!)...

And now, finally here is my question:
How can I avoid this problem? How can I measure the times of functions like "Sleep" properly?

thanks :)

Community
  • 1
  • 1
Idov
  • 5,006
  • 17
  • 69
  • 106
  • 2
    By design. Sleep is wall clock time, not thread time. – Hans Passant Jan 03 '11 at 19:00
  • You could always look at your own posts and find it - http://stackoverflow.com/questions/4574727/measuring-time-of-a-profiled-function – Greg Domjan Jan 03 '11 at 19:00
  • Hans@: Is there a way to get the thread time? Greg@: what in my last post can help me with this? – Idov Jan 03 '11 at 19:52
  • @Greg, it's not that he couldn't find it. He obviously found it since he linked to it. His concern was that *nobody else* would see it because it wasn't showing up on the front page anymore. (Idov, editing an old question also puts it on the front page, so don't worry about that. But this question looks like it could stand alone, not just as a small update to your previous question, so posting a new one as you've done here is fine.) – Rob Kennedy Jan 05 '11 at 18:44
  • 1
    nit: On stackoverflow we have questions, not threads. This isn't a discussion forum. – Sam Miller Jan 05 '11 at 20:04

2 Answers2

4

sleep methods almost never actually perform the "spin" mechanic you're describing- there's no reason to waste so much CPU time when all it really needs to do is set a timer inside the OS, and then simply stop running until reawakened by the timer. If a process that is already frozen due to a sleep call is frozen again because you suspended it, then it's simply suspended twice; the "alarm clock" calls back and releases its suspension, but the application is still suspended because you suspended it. If you unsuspend it before the sleep wears off, your suspend/unsuspend will have simply had no effect.

As such, it is simply impossible for a thread to know or care about why a sleep took a different time from what was expected. It simply was not running code while it was sleeping. It stopped running code, and then it started running code again some time later, and checking the wall clock will simply tell it how long it was out, not what caused it to be frozen during that time. (Maybe it was low priority, and the OS was very busy, and it simply took that long to schedule it to run again after the sleep ended.)

The closest you can do is to write your own sleep method and use it only for debugging purposes. (It should probably call into the system sleep method when not in debugging mode, so you don't have to change the code outside the function- use conditional compilation via #ifdef DEBUG/#endif.) That sleep should do exactly what you suggest: count ticks until the "wall clock" says it's waited long enough, and if there's an unexpectedly large gap between ticks, push the deadline out further because that time didn't "count".


All that said:

Maybe you've asked the wrong question here. Why are you trying to profile sleep anyway, and make it stable across manually stopping the program? Accurate profiling generally goes out the window anyway once you're freezing the program externally- it throws off almost all the timing-related properties of the program, especially with regard to CPU memory cache behavior.

Adam Norberg
  • 3,028
  • 17
  • 22
  • I'm writing my own little profiler and I ran it on a "Sanity-Check" just to test the timing. I actually tried to suspend a sleeping process (after 2 seconds, while it was supposed to sleep 1 minute) and waited for a few minutes (writing my question). when I resumed it - it stopped sleeping immediately... so I don't understant how it adds up with your answer. :) – Idov Jan 03 '11 at 18:46
  • Windows uses the explicit mechanic of a "suspend count" on a thread (or process), and while I don't know if it's explicitly part of Linux (I haven't studied the kernel enough), it's a useful abstraction. A thread with a suspend count of 0 is running. When `sleep` is called, the suspend count goes up by 1 and the process freezes because the suspend count is above 0. When the timeout hits, the suspend count drops by 1. When you stopped the program, the suspend count increased. So at T=-1, suspend count S=0. Sleep at T=0, S=1. You break in at T=2, S=2 for your break. T=60, S=1; resume@T=900, S=0. – Adam Norberg Jan 03 '11 at 19:06
  • yes! that is my problem. T = 60 -> S = 1, but T = 60 in REAL time. therefore the process while it's not suspended would sleep 60-X seconds, and X seconds while it is suspended. – Idov Jan 03 '11 at 19:25
  • Technically, the process is suspended the entire time. It's just that for T=[0-2], it's suspended because of the `sleep` call, for T=[2-60] it's suspended _both_ because of the `sleep` call and your manual break, and for T=[60-900], it's suspended because of your manual break. `sleep` is something the OS handles for your process, not something the process itself is especially cognizant of. – Adam Norberg Jan 03 '11 at 19:30
  • Yes, I got that :) But what I was asking is how I can make the process sleep for 60 seconds ONLY because of the "sleep" call, I don't care how much extra time it sleeps because of my manual break. – Idov Jan 03 '11 at 19:35
  • The closest approximation I can suggest is a loop that sleeps sixty times for one second each. `for(int i = 0; i < 60; ++i){sleep(1000);}` – Adam Norberg Jan 03 '11 at 19:38
  • I don't want to change how the profiled process uses "Sleep". I just want to measure it. – Idov Jan 03 '11 at 19:43
  • 1
    You can't. There is no way to do this. The process is not stopped differently when you stopped it and when the process is sleeping; it is simply stopped. The OS doesn't really care why; it just knows it has a timer that should decrease the freeze count at a certain point, and it's not keeping track of anything else. There is simply nothing that can be measured here. – Adam Norberg Jan 03 '11 at 20:28
0

I got it.
I'll just check if the process is already suspended when I suspend it, and if so - I'll consider the time of my manual suspension as well.
thanks everbody :)

Idov
  • 5,006
  • 17
  • 69
  • 106