使用 ManualResetEventSlim 代替 ManualResetEvent 的最短等待时间是多少?

发布于 2025-01-13 14:06:29 字数 1411 浏览 0 评论 0原文

从 NET 4 开始,我可以使用 ManualResetEventSlim 类,在阻塞之前进行一些旋转,以便在阻塞时间很小时(我没有上下文切换)的情况下获得时间优化。

我想使用基准来衡量这次时间有多短,以便或多或少地了解首选使用 ManualResetEventSlim 而不是经典 ManualResetEvent< 所需的等待时间。 /代码>。

我知道这个衡量标准取决于 CPU,不可能先验地知道旋转时间,但我希望有一个数量级。

我编写了一个基准类,以获得使 ManualResetEventSlim 优于 ManualResetEvent 的最小 MillisecondSleep。

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();
    }
}

结果如下

Benchmark result

如您所见,我发现仅使用 Thread.Sleep(0) 即可提高性能。此外,我看到 1 毫秒和 10 毫秒的平均时间为 15 毫秒。 我错过了什么吗?

是否只有 0 毫秒等待才最好使用 ManualResetEventSlim 而不是 ManualResetEvent

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

Benchmark result

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我做我的改变 2025-01-20 14:06:29

来自优秀的《C# 9.0 in a Nutshell》一书:

等待或发出 AutoResetEventManualResetEvent 信号大约需要一微秒(假设没有阻塞)。

ManualResetEventSlimCountdownEvent 在短等待场景中速度可以提高 50 倍,因为它们不依赖操作系统并且明智地使用旋转结构。然而,在大多数情况下,信令类本身的开销不会造成瓶颈;因此,很少有人考虑它。

希望这足以给您一个粗略的数量级。

From the excellent C# 9.0 in a Nutshell book:

Waiting or signaling an AutoResetEvent or ManualResetEvent takes about one microsecond (assuming no blocking).

ManualResetEventSlim and CountdownEvent 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文