Search code examples
multithreadingdelphimessagingsleep

Pause a thread for less than one millisecond


In a messaging client test application, the producer thread needs to be throttled to avoid flooding the server.

As the transfer rates are around 25,000 messages per second (40 microseconds per message), the delay caused by Sleep(1) would far too long.

How to make thread sleep less than a millisecond on Windows contains some information related to the Windows API. Is there a code snippet, class or library for Delphi?


Following Bens answer I found that Sleep with different values below 15 also gives different transfer rates (Windows Vista):

Sleep(1) after every 20 messages:

00:02 tx/rx 25740/3705 12831/1846 msgs/sec (77/541 microsecs/msg)
00:04 tx/rx 53101/7405 13255/1848 msgs/sec (75/541 microsecs/msg)
00:06 tx/rx 79640/11288 13260/1879 msgs/sec (75/532 microsecs/msg)
00:08 tx/rx 104520/14562 13055/1818 msgs/sec (76/550 microsecs/msg)
00:10 tx/rx 130760/18829 13066/1881 msgs/sec (76/531 microsecs/msg)

Sleep(5) after every 20 messages:

00:02 tx/rx 7640/3622 3812/1807 msgs/sec (262/553 microsecs/msg)
00:04 tx/rx 14660/10794 3661/2695 msgs/sec (273/371 microsecs/msg)
00:06 tx/rx 21480/18171 3577/3026 msgs/sec (279/330 microsecs/msg)
00:08 tx/rx 28140/25642 3515/3203 msgs/sec (284/312 microsecs/msg)
00:10 tx/rx 34980/32692 3496/3267 msgs/sec (286/306 microsecs/msg)

This was unexpected after reading the comment about the lower limit for busy waiting

And the values without throttling

00:02 tx/rx 44065/494 21988/246 msgs/sec (45/4065 microsecs/msg)
00:04 tx/rx 90493/756 22595/188 msgs/sec (44/5319 microsecs/msg)
00:06 tx/rx 142982/907 23810/151 msgs/sec (41/6622 microsecs/msg)
00:08 tx/rx 192562/1144 24055/142 msgs/sec (41/7042 microsecs/msg)
00:10 tx/rx 237294/1395 23717/139 msgs/sec (42/7194 microsecs/msg)

Solution

  • Send 20 messages and then sleep for 1 millisecond?

    You can't sleep for less than the scheduler quantum, unless you have a hardware interrupt other than the system timer. Read the answers in the question you linked, they explain why the suggested approach doesn't actually work.

    Even with this approach you might sleep longer than 1ms, or since the messages aren't sent instantaneously, the whole operation will surely take longer than 1ms, reducing the overall rate.

    So, inspect a precision clock source every time you wake, and calculate how many messages to send based on elapsed time, don't use a constant 20.