Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Large Number of Timers

Tags:

c#

.net

timer

I need to write a component that receives an event (the event has a unique ID). Each event requires me to send out a request. The event specifies a timeout period, which to wait for a response from the request.

If the response comes before the timer fires, great, I cancel the timer. If the timer fires first, then the request timed out, and I want to move on.

This timeout period is specified in the event, so it's not constant. The expected timeout period is in the range of 30 seconds to 5 minutes.

I can see two ways of implementing this.

  1. Create a timer for each event and put it into a dictionary linking the event to the timer.
  2. Create an ordered list containing the DateTime of the timeout, and a new thread looping every 100ms to check if something timed out.

Option 1 would seem like the easiest solution, but I'm afraid that creating so many timers might not be a good idea because timers might be too expensive. Are there any pitfalls when creating a large number of timers? I suspect that in the background, the timer implementation might actually be an efficient implementation of Option 2. If this option is a good idea, which timer should I use? System.Timers.Timer or System.Threading.Timer.

Option 2 seems like more work, and may not be an efficient solution compared to Option 1.

Update

The maximum number of timers I expect is in the range of 10000, but more likely in the range of 100. Also, the normal case would be the timer being canceled before firing.

Update 2

I ran a test using 10K instances of System.Threading.Timer and System.Timers.Timer, keeping an eye on thread count and memory. System.Threading.Timer seems to be "lighter" compared to System.Timers.Timer judging by memory usage, and there was no creation of excessive number of threads for both timers (ie - thread pooling working properly). So I decided to go ahead and use System.Threading.Timer.

like image 208
Mas Avatar asked Dec 06 '13 15:12

Mas


People also ask

What is the maximum number of timers that a process can have?

Windows 3.0 increased this to 32.

Are timers thread safe?

Timer is not thread-safe.


2 Answers

I do this a lot in embedded systems (pure c), where I can't burn a lot of resources (e.g. 4k of RAM is the system memory). This is one approach that has been used (successfully):

  1. Create a single system timer (interrupt) that goes off on a periodic basis (e.g. every 10 ms).
  2. A "timer" is an entry in a dynamic list that indicates how many "ticks" are left till the timer goes off.
  3. Each time the system timer goes off, iterate the list and decrement each of the "timers". Each one that is zero is "fired". Remove it from the list and do whatever the timer was supposed to do.

What happens when the timer goes off depends on the application. It may be a state machine gets run. It may be a function gets called. It may be an enumeration telling the execution code what to do with the parameter sent it the "Create Timer" call. The information in the timer structure is whatever is necessary in the context of the design. The "tick count" is the secret sauce.

We also have created this returning an "ID" for the timer (usually the address of the timer structure, which is drawn from a pool) so it can be cancelled or status on it can be obtained.

Convenience functions convert "seconds" to "ticks" so the API of creating the timers is always in terms of "seconds" or "milliseconds".

You set the "tick" interval to a reasonable value for granularity tradeoff.

I have done other implementations of this in C++, C#, objective-C, with little change in the general approach. It is a very general timer subsystem design/architecture. You just need something to create the fundamental "tick".

I even did it once with a tight "main" loop and a stopwatch from the high-precision internal timer to create my own "simulated" tick when I did not have a timer. I do not recommend this approach; I was simulating hardware in a straight console app and did not have access to the system timers, so it was a bit of an extreme case.

Iterating over a list of a hundreds of timers 10 times a second is not that big a deal on a modern processor. There are ways you can overcome this as well by inserting the items with "delta seconds" and putting them into the list in sorted order. This way you only have to check the ones at the front of the list. This gets you past scaling issues, at least in terms of iterating the list.

Was this helpful?

like image 81
FuzzyBunnySlippers Avatar answered Oct 14 '22 03:10

FuzzyBunnySlippers


You should do it the simplest way possible. If you are concerned about performance, you should run your application through a profiler and determine the bottlenecks. You might be very surprised to find out it was some code which you least expected, and you had optimized your code for no reason. I always write the simplest code possible as this is the easiest. See PrematureOptimization

I don't see why there would be any pitfalls with a large number of timers. Are we talking about a dozen, or 100, or 10,000? If it's very high you could have issues. You could write a quick test to verify this.

As for which of those Timer classes to use: I don't want to steal anyone elses answer who probably did much more research: check out this answer to that question`

like image 30
dferraro Avatar answered Oct 14 '22 02:10

dferraro