Problem with Sleep and GetTickCount().

This is a discussion on Problem with Sleep and GetTickCount(). within the C Programming forums, part of the General Programming Boards category; Hello, while working on some application, I encountered some weird behaviours and started tracking the problem, until I found out ...

  1. #1
    Registered User
    Join Date
    Feb 2008
    Posts
    7

    Problem with Sleep and GetTickCount().

    Hello,

    while working on some application, I encountered some weird behaviours and started tracking the problem, until I found out what it was. GetTickCount() didn't seem to properly behave. While trying to find out what it was, I used Sleep, and to my surprise, even weirder beharviours appeared!

    I coded a little test program that still shocks me. Hope someone can help.

    The program is:

    Code:
    #include <windows.h>
    #include <stdio.h>
    
    int main()
    {
        long pret = GetTickCount(), post;
    
        while (1)
        {
            post = GetTickCount();
    	printf("\n&#37;ld", post - pret /*- 100*/);
            pret = post;
            //Sleep(100);
        }
    }
    I've tried that program in two computers. The behaviour on these computers is different (in one of them it actually works as expected!).

    Computer one (it works as I expected it to):
    -With comments: The output is generally 0, sometimes 1.
    -Without comments: The output is generally 0, sometimes 1.

    Computer two:
    -With comments: The output is generally 0, sometimes 15 or 16! (Never something else)
    -Without comments: The output is an integer in the [-10, 10] interval.


    The initial thing that bugged me was that 15/16. It is weird, as GetTickCount() should be returning the same value for a few iterations (since the iteration takes less than a millisecond) and then return that old value plus one. (Hence the correct output on computer one).

    Then, one would suppose that removing those comments would only help me seeing the output in a more relaxed way (those printf's did fill the console quickly), but shouldn't affect the output. Well, negative numbers appeared. Is Sleep() not exact on some computers, but is in others?

    I hope someone can help me, particularly with the GetTickCount() returning 0,0,...,0,15,0,...,0 problem. I really don't care much about Sleep() being exact or not, but it would still be interesting to know too.

    Thanks in advance!
    Last edited by IamBMF; 02-02-2008 at 01:47 PM.

  2. #2
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    What kind of computers are they? What CPU & speed...

  3. #3
    Registered User
    Join Date
    Feb 2008
    Posts
    7
    Computer one (works as expected) is a Pentium 4 (2 GHz), 256MB RAM. It is a laptop.
    Computer two (does not works as expected) is a Pentium 4 (3.2 GHz), 1GB RAM. It is not a laptop.

    I'm running Windows XP on both of them.
    Last edited by IamBMF; 02-02-2008 at 02:23 PM.

  4. #4
    Registered User
    Join Date
    Feb 2008
    Posts
    7
    Sorry to double post, but I did a new test, and seem to have found one of the errors:

    Code:
    #include <windows.h>
    #include <stdio.h>
    
    int main()
    {
        while (1)
            printf("\n%ld", GetTickCount());
    }
    GetTickCount() seems to update it's value in 15 milliseconds each time on computer two (which is horrible!), but in 1 millisecond each time on computer one.

    I still don't know why, and still haven't solved what's wrong with Sleep. I'll keep investigating.

  5. #5
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,788
    Remember that GetTickCount is not very accurate. Or isn't supposed to be.
    However, it should be possible to affect that with SetSystemTimeAdjustment.
    Or you could try to use timeGetTime API.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Registered User
    Join Date
    Feb 2008
    Posts
    7
    Thank you very much. timeGetTime works very well.

    What about Sleep()? Is it also not supposed to be accurate?

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Sleep is based on the scheduler, so it will NEVER be accurate. If there is no load on the machine, it may be REASONABLY accurate [within the precision of the timer, which may be 1ms, 10ms or some other amount, depending on the current system settings], but as soon as the machine is loaded (as in, there are more than one application per processsor core competing for CPU time) it won't be. The only guarantee about Sleep is that it doesn't come back immediately, but the length of the sleep is dependant on whether another thread is available to run on the current CPU core or not.

    You can mess with the priority of your task, but that only works if no other task is raising it's own priority, so the problem persists.

    Windows is not a RTOS.

    What is the problem you are trying to solve where you need "precise" sleeps?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,788
    Sleep will guarantee to sleep "at least" n milliseconds. It wasn't designed to be accurate.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User
    Join Date
    Feb 2008
    Posts
    7
    @matsp: I do not need "precise" sleeps, it's just that I found out it wasn't precise while trying to solve my GetTickCount() problem, and was curious to know why. =)

    @Elysia: That's weird, because this:

    Code:
    #include <windows.h>
    #include <stdio.h>
    
    int main()
    {
        long pret = GetTickCount(), post;
    
        while (1)
        {
            post = GetTickCount();
    	printf("\n&#37;ld", post - pret - 100);
            pret = post;
            Sleep(100);
        }
    }
    Returns negative values at times. Which means it is sleeping less than 100 milliseconds. Right?
    Last edited by IamBMF; 02-02-2008 at 06:28 PM.

  10. #10
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,788
    Indeed. The documentation is contradicting itself. Oh woe, Microsoft!
    Suspends the execution of the current thread for at least the specified interval.
    That means it would at sleep n milliseconds, right?
    If dwMilliseconds is less than the resolution of the system clock, the thread may sleep for less than the specified length of time.
    Oops. It seems it can sleep "less" too. Haha.
    Microsoft made a blunder.

    So yes, it appears it can sleep less or more, but around 100 ms. Not precise.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User
    Join Date
    Feb 2008
    Posts
    7
    I see.

    Thanks a lot for your help! This looks like a community where one should stay! =P

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I think the conclusion is that you can't rely on the Sleep() being precise.

    The basic principle of any sleep operation is that you figure out how many timer ticks that is required for the sleep period. The problem comes if the sleep period isn't an even number of timer ticks, e.g. the timer is 20ms and you ask for 50ms - you can't sleep 2.5 timer ticks, but rather have to sleep either 2 or 3 ticks. The start of the sleep would also not always be requested at the beginning of a tick, so it may be around half a tick on average from the sleep starts until the first tick comes in - and in most cases, the OS has no good way to find out exactly how far into the tick the request comes.

    This works fine when you sleep for relatively long periods, like 1 second or so, but if the time is a small number of timer ticks, the "error element" of +/- 1 tick would cause a big deviation.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  13. #13
    Registered User
    Join Date
    Feb 2008
    Posts
    7
    Oh my God. This is driving me mad.

    Today my laptop (computer one) seems not to be accurate with GetTickCount() either! It worked perfectly yesterday!

    Using timeGetTime on computer two solved it, but now I can't get my laptop to be accurate, not even if I use timeGetTime on it!

    Please help, I really need to get precise down to the millisecond. This makes no sense to me.
    Last edited by IamBMF; 02-03-2008 at 07:40 AM.

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You do realize that laptops are often undercooled and thus rely on a thermal throttling to adjust the speed to match the thermal capacity of the system - this means that if the processor gets too hot, just stop it for a short while.

    There's also general power management in the Laptop - this can also put the machine to sleep for short periods of time.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21