How to make sleep flow less than a millisecond on Windows

On Windows, I have a problem that I have never encountered on Unix. Here's how to get a thread to sleep in less than a millisecond. On Unix, you usually have the choice (sleep, sleep, and apply) to suit your needs. However, on Windows there is only a dream with millisecond granularity.

On Unix, I can use the select system call to create a microsecond sleep, which is pretty simple:

 int usleep(long usec) { struct timeval tv; tv.tv_sec = usec/1000000L; tv.tv_usec = usec%1000000L; return select(0, 0, 0, 0, &tv); } 

How can I do the same in windows?

+43
c ++ windows sleep winapi
Sep 17 '08 at 16:37
source share
18 answers

On Windows, using select forces you to enable the library

-2
Sep 17 '08 at 16:39
source share

This indicates a misunderstanding of sleep functions. The parameter that you go through is the minimum time for sleep. There is no guarantee that the flow will wake up after the specified time. In fact, threads will not “wake up” at all, but rather are selected for execution by the scheduler. The scheduler can wait much longer than the requested sleep duration to activate the thread, especially if another thread is still active at that moment.

+87
Sep 17 '08 at 16:40
source share

As Joel says, you cannot meaningfully “sleep” (that is, refuse the planned processor) for such short periods. If you want to linger for a short time, you need to unscrew, re-check the appropriate high-resolution timer (for example, "performance timer") and hope that something with a high priority will not remove you anyway.

If you really need accurate delays in such short times, you should not use Windows.

+41
Sep 17 '08 at 16:45
source share

Use the high resolution timers available in winmm.lib. See this for an example.

+20
Sep 17 '08 at 16:46
source share

Yes, you need to understand the time slices of your OS. On Windows, you won’t even get 1 ms resolution unless you change the time slice to 1 ms. (Using, for example, timeBeginPeriod () / timeEndPeriod ()) This still does not guarantee anything. Even a small load or one crappy device driver will drop everything.

SetThreadPriority () helps, but is pretty dangerous. Bad device drivers can kill you.

You need an ultra-controlled computing environment to make this ugly stuff in general.

+9
Sep 17 '08 at 16:49
source share

If you want so granularity that you are in the wrong place (in user space).

Remember that if you are in user space, your time is not always accurate.

The scheduler can start your thread (or application) and schedule it, so you depend on the OS scheduler.

If you are looking for something exact, you need to go: 1) In the kernel space (for example, drivers) 2) Select RTOS.

In any case, if you are looking for some granularity (but remember the problem with user space), see the QueryPerformanceCounter Function and the QueryPerformanceFrequency Function on MSDN.

+6
Sep 17 '08 at 18:03
source share

As several people have noted, sleep and other related features are, by default, dependent on a “system tick”. This is the smallest unit of time between OS tasks; the scheduler, for example, will not run faster than this. Even with a real-time OS, the system tick is usually at least 1 ms. Although this is customizable, it has implications for the entire system, not just your sleep functionality, as your scheduler will work more often and potentially increase the overhead of your OS (the amount of time it takes to start the scheduler, as well as the amount of time it takes to complete the task).

The solution to this is to use an external high speed sync device. Most Unix systems will let you specify your timers and such different clocks to use, unlike the default system clock.

+5
Sep 17 '08 at 18:03
source share

What are you waiting for, why do you need such accuracy? In general, if you need to indicate this level of accuracy (for example, due to dependence on any external equipment), you are on the wrong platform and should look at the real-time OS.

Otherwise, you should consider whether there is an event that you can synchronize, or in the worst case, just waiting for the CPU and using a high-performance API counter to measure elapsed time.

+4
Sep 17 '08 at 16:47
source share

Typically, sleep will continue, at least until the next interruption of the system occurs. However, this depends on the media timer resource settings. Something close to 1 ms can be set, some hardware even allows operation during interrupt periods of 0.9765625 (ActualResolution provided by NtQueryTimerResolution will show 0.9766, but this is really wrong. They simply cannot put the correct number into the ActualResolution format. It is 0, 9765625ms with 1024 interruptions on the second).

There is one exception that allows us to avoid due to the fact that sleep may be impossible less than the interruption period: this is the famous Sleep(0) . It is a very powerful tool and it is not used as often as needed! He refuses to be reminded of the cutoff time of the flow. Thus, the thread will stop until the scheduler forces the thread to receive the cpu service again. Sleep(0) is an asynchronous service; a call will make the scheduler respond regardless of interruption.

The second way is using a waitable object . A wait function, such as WaitForSingleObject() , can wait for an event. In order for the thread to sleep at any time, as well as once in microsecond mode, the thread needs to configure some service thread that will generate an event with the required delay. A sleep thread will install this thread and then suspend the wait function until the service thread sets the event.

Thus, any thread can "sleep" or wait at any time. A service stream can be of great complexity, and it can offer system services, such as synchronized events with a resolution in microseconds. However, microsecond resolution can cause the service thread to rotate in the high-resolution service during no more than one interruption period (~ 1 ms). If caution is taken, this may work very well, especially on multiprocessor or multicore systems. A 1 ms rotation does not deteriorate much in a multi-core system when the proximity mask for the calling thread and service thread is carefully masked.

Code, description and testing can be visited at Project Timestamp on Windows

+3
Jul 12 '12 at 16:12
source share

I have the same problem and nothing seems faster than ms, even Sleep (0). My problem is the connection between the client and the server application, in which I use the _InterlockedExchange function to check and set the bits, and then sleep (0).

I really need to do thousands of operations per second this way, and it doesn't work as fast as I planned.

Since I have a thin client that interacts with the user, which, in turn, calls the agent, which then speaks to the stream, I will go over soon to combine the stream with the agent so that the event interface is not required.

Just to give you guys an idea of ​​how slow this dream was, I ran a test for 10 seconds, performing an empty loop (getting something like 18,000,000 cycles), while with an event in place I got only 180,000 cycles. That is, 100 times slower!

+2
May 13 '09 at 20:02
source share

Actually using this usleep function will result in a large memory / resource leak. (depending on how often called)

use this corrected version (sorry, can’t edit?)

 bool usleep(unsigned long usec) { struct timeval tv; fd_set dummy; SOCKET s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); FD_ZERO(&dummy); FD_SET(s, &dummy); tv.tv_sec = usec / 1000000ul; tv.tv_usec = usec % 1000000ul; bool success = (0 == select(0, 0, 0, &dummy, &tv)); closesocket(s); return success; } 
+2
Sep 19 '09 at 16:34
source share
 #include <Windows.h> static NTSTATUS(__stdcall *NtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval) = (NTSTATUS(__stdcall*)(BOOL, PLARGE_INTEGER)) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtDelayExecution"); static NTSTATUS(__stdcall *ZwSetTimerResolution)(IN ULONG RequestedResolution, IN BOOLEAN Set, OUT PULONG ActualResolution) = (NTSTATUS(__stdcall*)(ULONG, BOOLEAN, PULONG)) GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwSetTimerResolution"); static void SleepShort(float milliseconds) { static bool once = true; if (once) { ULONG actualResolution; ZwSetTimerResolution(1, true, &actualResolution); once = false; } LARGE_INTEGER interval; interval.QuadPart = -1 * (int)(milliseconds * 10000.0f); NtDelayExecution(false, &interval); } 

yes, it uses some undocumented kernel functions, but it works very well, I use SleepShort (0.5); in some of my threds

+2
Jul 14 '15 at 15:57
source share

Like all those mentioned, there really are no guarantees regarding sleep time. But no one wants to admit that sometimes, on an unoccupied system, the usleep command can be very accurate. Especially with a heartless core. Windows Vista has it, and Linux has it since 2.6.16.

Ticker cores exist to help improve laptop performance: cf Intel PowerTop Utility.

In this state, I probably measured the Linux usleep command, which very closely followed the requested sleep time, up to a dozen and a half microseconds.

So maybe OP wants something that will work most of the time in the system at idle and be able to request microsecond scheduling! I would also like to do this on Windows.

Also Sleep (0) sounds like boost :: thread :: yield (), this terminology is clear.

I wonder if Boost -timed locks have better accuracy. Because then you can just block the mutex that no one ever releases, and when the timeout is reached, go on ... Timeouts are set using boost :: system_time + boost :: milliseconds and cie (deprecation time outdated).

+1
May 11 '12 at 15:50
source share

Try boost :: xtime and timed_wait ()

has nanosecond accuracy.

0
Sep 17 '08 at 17:00
source share

Just use Sleep (0). 0 is obviously less than a millisecond. That sounds funny, but I'm serious. Sleep (0) tells Windows that you have nothing to do now, but you want to be reviewed as soon as the scheduler starts again. And since it is obvious that a thread cannot be scheduled to run before the scheduler starts, this is the shortest possible delay.

Please note that you can pass the microsecond number to your sleeping value, but also does not work (__ int64 t) {Sleep (t / 1000); } - no guarantees to actually sleep during this period.

0
Sep 18 '08 at 8:59
source share

Try using SetWaitableTimer ...

0
Jul 03 '15 at 6:49
source share

A sleep function that is less than a millisecond is possible

I found that sleep (0) worked for me. In a system with a load of almost 0% on the CPU in the task manager, I wrote a simple console program, and the sleep (0) function slept for 1-3 consecutive microseconds, which is less than a millisecond.

But from the above answers in this thread, I know that the amount of sleep (0) can vary much more wildly than it does on systems with a large processor load.

But, as I understand it, the sleep function should not be used as a timer. It should be used so that the program uses the lowest percentage of the processor as possible and runs as often as possible. For my purposes, such as moving a projectile across the screen in a video game, is much faster than one pixel per millisecond, sleep (0) works, I think.

You just make sure that the waiting interval is less than the longest time that he will sleep. You do not use sleep as a timer, but only so that the game uses the minimum percentage of the processor. You would use a separate function that has nothing to do, it's a dream to find out when a certain amount of time has passed, and then move one pixel across the screen on the screen - at a time of 1/10 s of a millisecond or 100 microseconds.

The pseudocode will look something like this.

 while (timer1 < 100 microseconds) { sleep(0); } if (timer2 >=100 microseconds) { move projectile one pixel } //Rest of code in iteration here 

I know that the answer may not work for advanced problems or programs, but it may work for some or many programs.

0
Oct 31 '15 at 5:33
source share

If your goal is to “wait for a very short period of time” because you are doing a spinway, then the level of expectation that you can fulfill is increasing.

 void SpinOnce(ref Int32 spin) { /* SpinOnce is called each time we need to wait. But the action it takes depends on how many times we've been spinning: 1..12 spins: spin 2..4096 cycles 12..32: call SwitchToThread (allow another thread ready to go on time core to execute) over 32 spins: Sleep(0) (give up the remainder of our timeslice to any other thread ready to run, also allows APC and I/O callbacks) */ spin += 1; if (spin > 32) Sleep(0); //give up the remainder of our timeslice else if (spin > 12) SwitchTothread(); //allow another thread on our CPU to have the remainder of our timeslice else { int loops = (1 << spin); //1..12 ==> 2..4096 while (loops > 0) loops -= 1; } } 

So, if your goal is to just wait a bit, you can use something like:

 int spin = 0; while (!TryAcquireLock()) { SpinOne(ref spin); } 

The advantage here is that we wait longer each time, ultimately to sleep completely.

0
Apr 22 '17 at 21:18
source share



All Articles