SUMTEC -- There's a thing in my bloglet.

But it's not only one. It's many. It's the same as other things but it exactly likes nothing else...

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  263 随笔 :: 19 文章 :: 3009 评论 :: 74万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
昨天研究一个delegate的问题,研究了半天,找出了很多的东西来。但是就是有一点始终搞不清楚:为什么某个事件添加一次和添加两次,时间上会相差四倍呢?开始我觉得是递归调用的错,dudu说是运行时生成的问题。实际上现在我做的试验表明很可能大家都错了:

首先我们尝试一下1->2,我们会发现接口的时间增加成比例关系,也就是1->2,可是事件花费的时间则是1->4。这个就是我们觉得非常奇怪的地方,为什么会超出线形关系呢?我开始认为是递归调用的结果,后来发现不是这么回事,因为我做了一个模仿delegate/multicastdelegate的类(除了不是delegate之外,行为几乎一样),然后进行模拟。发现递归和循环之间的差别并不是很明显,基本上相差30%左右。但是同时你也能够发现,无论添加的事件是多少个,递归和循环一样,消耗的时间都保持着线形的关系。

看到这里我们非常的奇怪,既然不是递归的问题,那么难道是运行时产生代码的问题?那也不可能啊,因为那也应该保持着线形的关系啊。

好,现在我们继续做试验:如果我们继续添加事件,比如2->3,那么我们看到interface那边消耗的时间也是2->3,event呢,则是4->6。再比如3->4,interface消耗时间变化是3->4,event则是6->8。
好了,原因几乎就是一目了然了:event的问题仅仅出在1->2,其他地方实际上还是线形关系的。那么在1->2的时候到底发生了什么事情呢?联想一件事情,在昨天的几篇文章中的一篇提到:“由于是runtime的,所以executor会进行优化,但是这个特性并没有在现在的编译器里面很好的实现,只是未来的特性。同时我也不认为这个特性会被添加到1.1版本的运行库里面。”(大意如此)

所以我现在有理由假设一件事情:那就是如果一个委托只被分派了一次,那么这个委托的基类就是Delegate,或者用一个简化的函数实现Invoke。反之,如果这个委托被分派了多次,那么这个委托的基类就是MultiCaseDelegate,或者用一个比较复杂的函数实现Invoke。这就造成了1->2之间的超线性关系,而2->3、3->4则保持了线性关系的原因——仅仅是猜测。

由于目前也仅仅是一个猜测,我想还是需要更多的试验来证实这个想法。不过我最近可能要忙着做别的事情了,所以这个试验就留给各位来试验了。

注:这里面提到的“时间添加两次”的意思大概就是:
t.Event += new xxHandler(xx1);
t.Event += new xxHandler(xx2);
而不是:
t.Event1 += new xxHandler(xx1);
t.Event2 += new xxHandler(xx2);
posted on   Sumtec  阅读(1213)  评论(3编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
点击右上角即可分享
微信分享提示