巴解组织的辉煌与贫穷

 

基类,几个子类,其中一个子类被使用,取决于启动时设置的参数。这是一个众所周知的通用程序运行原则。有多少变体并不重要(即子类),这种情况应该是工作得非常快的,因为没有if和switch调用来改变程序的工作方式,只有在初始化过程中选择了所需的子类,然后一切工作都很直接和简单。

class CBase{
   private:
   public:
      virtual void Fun(){
      
      }
};

class CClass1:CBase{
   private:
   public:
      void Fun(){
      
      }
};

CClass1 * cl;

void OnInit(){

   cl=new CClass1;

}

然而......。

能有多少种不同的变体?一个合理的数字?10, 20, 100?即使有100个变体,switch的工作速度也比OOP快。

这里有一个用于比较性能的脚本。它比较了上述的OOP和一个带有函数的简单开关(并且调用了两个函数,其中一个函数的调用 很容易被抛弃)。

void ff(int z){

      switch(z){
         case 0:
         f0();
         break;

         ...

         case 99:
         f99();
         break;

      }
     
}
结果(调用f99)。

附加的文件:
test.mq4  9 kb
 
Integer:

可以有多少种不同的选择?一个合理的数字?10, 20, 100?即使有100个选择,switch也比OOP工作得快。

我想提醒大家不要以偏概全:这样的效果在mql中是合理的,因为它使用了虚拟的 "伪指针"--本质上是指向真实地址的内部(隐藏)哈希表的句柄。为了解决这样的指针,需要大量的额外时间,远远超过直接指针寻址。 我没有测量过,但很可能在dotNET语言和其他类似的实现中也会发现同样的指针 "瓶颈 "效应。

有 "真正的 "指针的语言不会有这种效果,开关会在那里输掉--选择的列表越大。

所以OOP本质上与此无关......

 
MetaDriver:

我想提醒大家不要以偏概全,这样的效果在mql中是合理的,因为它使用了虚拟的 "伪指针"--本质上是指真实地址的内部(隐藏)哈希表。为了解决这样的指针,需要大量的额外时间,远远超过直接指针寻址。 我没有测量过,但很可能在dotNET语言和其他类似的实现中也会发现同样的指针 "瓶颈 "效应。

在有 "真正的 "指针的语言中,这种效果不会发生,开关会输在那里--选择列表越大。

所以OOP本质上与此无关......

很明显,这只是编译器本身的问题,因此,在 "正确 "的编译下,上述例子的执行时间 会相等。
 
icas:
很明显,这只是编译器本身的问题,因此,如果上述例子被 "正确 "编译,执行时间 将相等。
正确性 "的概念取决于规则,因此它是没有意义的。;)
 

我直接指出这个错误:f函数是空的,完全被编译器剪掉了。也就是说,实际上没有函数调用。我也不确定ff函数会退化到什么状态,以及它最终会不会被内联到for循环里面,从而连函数的调用都取消了。

另一方面,虚拟方法不能被切断--它总是被调用。结果是,在一种情况下,循环只是在旋转,而在另一种情况下,调用是在循环中。

在任何测试中,你必须首先证明其正确性,然后才去看结果。

 

这里有一个非空的函数。

附加的文件:
test2.mq4  11 kb
 

这里是所有的函数,它们是独一无二的,而且,通过开关调用,比类方法 更复杂。

附加的文件:
test3.mq4  12 kb
 
Integer:

这里是所有的函数,它们是独一无二的,而且,通过开关调用,比类方法 更复杂。

真是一团糟...

你听说过关于内联的事情吗?那积极的内联呢?

简单的函数体通常会发生什么,一个好的优化编译器会对它们做什么?这不是1995年,是吗?

 
MetaDriver:

我想提醒大家不要以偏概全,这样的效果在mql中是合理的,因为它使用了虚拟的 "伪指针"--本质上是指向内部(隐藏的)真实地址哈希表的句柄。为了解决这样的指针,需要大量的额外时间,远远超过直接指针寻址。 我没有测量过,但很可能在dotNET语言和其他类似的实现中也会发现同样的指针 "瓶颈 "效应。

在有 "真正的 "指针的语言中,不会有这样的效果,在那里,开关将失去--选择列表越大。

所以OOP本质上与此无关......

是的,这里是C调。)


7550021 (开关)
2250004 (OOP)
7325029 (开关)
2050015 (OOP)
7550049 (开关)
2150005 (OOP)
7575031 (开关)
2325009 (OOP)
8025038(开关)
2200004 (OOP)
7150027 (开关)
2050014 (OOP)
7375029 (开关)
2200005 (OOP)
7550022 (开关)
1950003 (OOP)
7100021(开关)
2695083 (OOP)
7360033 (开关)
2200008 (OOP)
7825029 (开关)
1925010 (OOP)
7325025 (开关)
2025006 (OOP)
6850035 (开关)
2525014 (OOP)
7750027 (开关)
1975007 (OOP)
8195225 (开关)
2050004 (OOP)
6950020(开关)
2425006 (OOP)
7275029 (开关)
2225015 (OOP)
7050037 (开关)
2200007 (OOP)
7375030(开关)

 

开始任何测试时,都要证明它是正确的,并实际测量它声称要测量的东西。

上面介绍的内容包含了惊人的错误,表明作者完全不了解编译机制和代码的工作原理。

 
Renat:

开始任何测试时,都要证明它是正确的,并实际测量它声称要测量的东西。

上面介绍的内容包含了惊人的错误,表明作者完全不了解编译机制和代码的工作原理。

我为什么要了解编译机制?只是要相信一个坏的结果比一个好的结果好吗? 结果才是最重要的。