C # - using Thread.Sleep () so that my loop runs several hundred times per second

I am developing an application that analyzes financial data in real time. Currently, my main computing cycle has the following design:

long cycle_counter=0; while (process_data) { (analyse data, issue instruction - 5000 lines of straightforwasrd code with computations) cycle_counter++; Thread.Sleep(5); } 

When I run this application on my laptop (one Core i5 processor), the cycle runs 200-205 times per second - sort of as expected (unless you worry about why it runs more than 200 times per second).

But when I deploy the application to a "real" workstation, which has 2 6-core Xeon processors and 24 GB of RAM and loads Win7 in about 3 seconds, the application starts the cycle about 67 times per second.

My questions:

  • Why is this happening?

  • How can I affect the number of runs per second in this situation?

  • Are there any better solutions for starting a cycle 200-1000 times per second? Now I'm thinking of simply removing Thread.Sleep () (the way I use it here has been criticized a lot). With 12 cores, I have no problem using a single core just for this loop. But do I have a drawback of such a solution?

Thanks for your ideas.

+7
multithreading c #
source share
6 answers

Windows is not a real-time operating system (RTOS), so you cannot determine exactly when your thread will resume. Thread.Sleep(5) really means "wake me up no earlier than 5 ms." Actual sleep time is determined by specific equipment and mainly by system load. You can try to solve the problem of system load to run the application with a higher priority .

BTW, System.Threading.Timer is the best approach (the above comments still apply).

+3
source share

The approach you take is simply fundamentally disrupted. Polling strategies are usually a bad way, and anytime you do a Dream for a reason other than “I want to return the rest of my time to the operating system,” you are probably doing something wrong.

The best way to approach the problem:

  • Make a raw workflow queue
  • Make one thread that queues a new job
  • Create n threads that do the work from the queue and do the work. n must be the number of processors that have a minus. If you have more than n threads, then at least two threads trade with CPU time, which makes them slower!
  • Worker threads do nothing but sit in a loop, doing work from a queue and doing work.
  • If the queue is empty, then take work out blocks.
  • When a new job arrives, one of the blocked threads is activated.

How to create a queue with these properties is a well-known problem called the "Manufacturer / Consumer Problem". There are many articles on how to do this in any implementation of blocking producer-consumer queues. I recommend finding an existing debugged one rather than trying to write your own; The right decision can be difficult.

+6
source share

Sleep resolution is dictated by the current timer interval and is usually 10 or 15 milliseconds, depending on the release of Windows. This can be changed, however, by issuing the timeBeginPeriod command. See this answer .

+3
source share

Check the actual frequency of your timer: many hardware timers have actual resolution

  65536 ticks per hour = 65536 / 3600 = 18.204 ticks per second 

The so-called constant is 18.2, so the actual resolution of the timer is 1 / 18.2 = 55 ms; in the case of Sleep(5) this means that depending on the rounding, either Sleep(0) or Sleep(55) .

+1
source share

Not sure if this is the best approach, but a different approach.
Try BlockingCollection, and all you do in the producer is add and sleep.
Then the consumer has the opportunity to work full time, if necessary.
This still does not explain why higher-powered PCs run less cycles.

+1
source share

Is it possible to run a cycle 200 times per second on average?

 var delay = TimeSpan.FromMillseconds(5); while (process_data) { Console.WriteLine("do work"); var now = DateTime.Now; if (now < nextDue) System.Threading.Thread.Sleep(nextDue - now); nextDue = nextDue.Add(delay); } 

Using this method, your loop will stumble somewhat, but on average it should be OK, because the code does not depend on either Sleep permission or DateTime.Now permission.

You can even combine this approach with a timer.

+1
source share

All Articles