From NET 4 I can use the ManualResetEventSlim
class that make a little spinning before blocking in order to get a time optimization if the blocking time is little (I have no context switch).
I'd like to measure using a benchmark how little is this time in order to know, more or less, the amount of wait time necessary to prefer using a ManualResetEventSlim
instead of a classic ManualResetEvent
.
I know that this measure is CPU dependent, it is impossible to know a priori the Spin time, but I'd like to have an order of magnitude.
I wrote a benchmark class in order to get the minimum MillisecondSleep that make ManualResetEventSlim
better than ManualResetEvent
.
public class ManualResetEventTest
{
[Params(0, 1, 10)]
public int MillisecondsSleep;
[Benchmark]
public void ManualResetEventSlim()
{
using var mres = new ManualResetEventSlim(false);
var t = Task.Run(() =>
{
mres.Wait();
});
Thread.Sleep(MillisecondsSleep);
mres.Set();
t.Wait();
}
[Benchmark]
public void ManualResetEvent()
{
using var mres = new ManualResetEvent(false);
var t = Task.Run(() =>
{
mres.WaitOne();
});
Thread.Sleep(MillisecondsSleep);
mres.Set();
t.Wait();
}
}
And the result is the following
As you can see I found a improved performance only using a Thread.Sleep(0). Furthermore I see a 15ms mean time with both 1 and 10 ms. Am I missing something?
Is it true that only with the 0 ms wait it is better to use a ManualResetEventSlim
instead of ManualResetEvent
?
CodePudding user response:
From the excellent C# 9.0 in a Nutshell book:
Waiting or signaling an
AutoResetEvent
orManualResetEvent
takes about one microsecond (assuming no blocking).
ManualResetEventSlim
andCountdownEvent
can be up to 50 times faster in short-wait scenarios because of their nonreliance on the OS and judicious use of spinning constructs. In most scenarios, however, the overhead of the signaling classes themselves doesn't create a bottleneck; thus, it is rarely a consideration.
Hopefully that's enough to give you a rough order of magnitude.