消除C#中的访客模式

时间:2017-09-03 11:33:37

标签: c#

我的代码如下:

Accept(IVisitor)

数组中的每个元素都实现UrlFetch接口,该接口具有headers方法。只有标准的访客模式。

在测量性能的同时,我得出的结论是,接口调用太慢了,在这段代码中,性能至关重要。根据您的经验,消除任何虚拟或接口呼叫的最佳选择是什么?检查具体类型的if语句?带有switch / case的每个元素的枚举(在这种情况下,代码的结构是不需要强制转换的)?还有别的吗?

P.S。我无法对数组中的项进行排序。订单很重要。因此,我不能按具体类型对它们进行排序以帮助进行分支预测。

2 个答案:

答案 0 :(得分:2)

我创建了以下程序。在我的笔记本电脑上,循环在8ms内运行了一百万次(这是Release版本,Debug是11ms左右)。这大约是0.000008ms来进行虚拟调度并增加一个int。究竟你有多快需要它?我怀疑你的表现测试或我的表现都出了问题。如果我的,我有兴趣听取改进建议。

通常,如果此级别的性能不够好,那么使用C#本身可能是一个问题。它的垃圾收集器有一个习惯,就是在循环中间冻结线程。如果在循环迭代中0.000008ms确实是一个问题,我怀疑汇编语言或C将是一个更好的选择。

a /home/store//.snapshot/hourly.0/d2/dd/d5d/f83-1 58K

答案 1 :(得分:1)

你这里没有一个虚拟电话,你有两个,但你只需要一个。首先,您的阵列可能通过IItem进行虚拟呼叫 - 但如果它们都是相同的类型,并且您知道类型(并且它已被密封),则不需要进行虚拟呼叫。

然后在访问对象中,您需要执行访问者想要执行的任何操作。这可能还涉及虚拟呼叫。

使用类型化的IVisitor可能会做得更好:

 interface IItem<TVisitor> : IItem 
     where TVisitor : IVisitor
 {
     void Accept(TVisitor visitor);
 }

 // Then
 SpecialVisitor visitor = ImplementsSpecialVisitor();
 foreach(var item in arrayOfSpecialItems){
     item.Accept<SpecialVisitor>(visitor);
 }