使用事件会产生多少性能开销?

19

我对编程还不是很熟悉,基于我有限的面向对象编程知识,我决定使用事件来在我的类之间进行通信。当然,这将导致相当多的事件。

我想知道使用事件是否会增加额外的开销?我认为,除非事件被执行(即,在一个类中有一个监听器根据事件触发执行函数),否则影响不会太大。但是,我并不十分了解C#中的事件,只想确认是否简单地触发事件就会产生显着的额外开销?


“显著”有多显著? - D Stanley
可能不重要...尝试搜索多播委托...这是.NET中事件工作方式的另一个名称。另请参阅此网址https://dev59.com/sHVC5IYBdhLWcg3wZwTj - John Gibb
我已经编辑了你的标题。请参考“问题的标题应该包含“标签”吗?”,在那里达成共识是“不应该”。 - John Saunders
5个回答

24

如果有人在很多年后偶然发现了这个问题,我使用了BenchMarkDotNet框架来测量事件所需时间。我已经区分了1个订阅者和100个订阅者之间的差异。

使用的测试代码:

private event EventHandler TestEventSingle;
private event EventHandler TestEventMultiple;

public OtherTests()
{
    TestEventSingle += OtherTests_TestEvent;

    for (int i = 0; i < 100; i++)
    {
        TestEventMultiple += OtherTests_TestEventMultiple;
    }
}

private void OtherTests_TestEventMultiple(object sender, EventArgs e)
{
    //Do something with the event...
}

private void OtherTests_TestEvent(object sender, EventArgs e)
{
    //Do something with the event...
}

[Benchmark]
public void InvokeEvent()
{
    TestEventSingle.Invoke(this, null);
}
[Benchmark]
public void InvokeEventMore()
{
    TestEventMultiple.Invoke(this, null);
}
[Benchmark]
public void CallMethod()
{
    OtherTests_TestEvent(this, null);
}
[Benchmark]
public void CallMethodMore()
{
    for (int i = 0; i < 100; i++)
    {
        OtherTests_TestEventMultiple(this, null);
    }
}

测试结果:

方法 平均值 误差 标准偏差
调用事件 1.6774纳秒 0.0246纳秒 0.0230纳秒
更多调用事件 192.2076纳秒 3.6115纳秒 3.3782纳秒
调用方法 0.0317纳秒 0.0106纳秒 0.0099纳秒
更多调用方法 37.1203纳秒 0.4147纳秒 0.3676纳秒

2
你能分享一些关于你的机器的信息吗?BenchmarkDotNet只能用于控制台应用程序吗?我的应用是WPF。 - Jim Broiles
@JimBroiles - 是的,它只与控制台相关。关键是要隔离你要测试的内容,然后运行基准测试。你需要在解决方案中为你的dotnet应用程序创建一个新项目。如果你已经将代码推入了SOC库中,你需要链接你的库;或者你需要复制你想要实际测试的代码。 - Paul Carlton

21
我想知道使用事件是否会增加额外的开销?我认为除非某个事件被执行(即在类中有一个侦听器根据事件执行函数),否则影响不大。
一般来说,这是正确的。 触发事件的标准模式除了检查调用列表以查看是否有订阅者之外,什么也不会做,如果没有侦听器,则返回,对于大多数情况而言,这将非常小,并且可能不会成为问题。
即使有订阅者,使用事件的开销仍然相当小,因为它们通过委托调用有效地调用订阅者处理程序,这仍然相对快速(尽管比直接方法调用慢)。只要不在非常紧密的循环中进行操作,它就很可能微不足道。
话虽如此,像任何性能问题一样,归结为测量。没有在您的情况下实际测量,就无法知道实际使用的重要性。为了确切地知道在特定情况下是否合理选择此设计,需要分析使用事件的性能以确保它不是一个重要问题。

12

使用事件会增加额外的开销吗?

嗯,是的 - 涉及到 MulitcastDelegate,代码检查以查看是否实际连接了事件处理程序等。

仅触发事件会有显著的额外开销吗?

啊 - 真正的问题。有开销,但这是显著的吗?只有通过测量才能回答。我的猜测是,您遇到的任何开销都不会很大(否则会有关于在性能关键应用中使用事件的警告,但我没有见过),并且您的应用程序中有其他部分对性能影响更大。


2
我不确定是否有人量化了开销,但对于大多数目的来说,它可能相当小。如果你是编程新手,那么你可能不打算一开始就编写超高性能的代码(如果你是这样的话,你可能不会使用C#,对吧?)
需要注意的是已发布事件的范围。你可能会遇到这样的情况:有几十个订阅者订阅了给定的事件,但实际上只有一两个订阅者真正关心该事件的特定实例。这可能会导致显著的开销。在这种情况下,值得研究“System.Observable”反应式编程范式。这可以通过允许你仅在那些真正关心给定事件的订阅者上调用处理程序来帮助限制过度广播。

那是我以前没有想过的事情,谢谢你提到这个。 - Garry Wong

-5

是的,有开销。是的,它可能很显著。这也不难证明。事件是多播委托,像方法一样,委托会阻塞直到完成。

以下是比较两者执行相同工作量的实际时间:

使用事件

完成所需时间271271.687毫秒= 271.271687秒

不使用事件

完成所需时间123214.514毫秒= 123.214514秒

在最适合的情况下使用事件。


9
由于您没有提供正在测试的代码,我们无法判断那些时间是否具有任何实际价值。 - arkon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接