The splendour and poverty of the PLO

 

Base class, several descendants, one of the descendants is used, depending on the parameters set at startup. This is a well-known principle of universal program operation. It doesn't matter how many variants there can be (i.e. descendant classes), this case is supposed to work very fast because there are no if and switch calls to change how the program works, only once the required descendant class is selected during initialization and then everything works straight and simple.

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

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

CClass1 * cl;

void OnInit(){

   cl=new CClass1;

}

However...

How many different variants can there be? A reasonable number? 10, 20, 100? Even with 100 variants, switch works faster than OOP.

Here is a script for comparing performance. It compares the above OOP and a simple switch with functions (and two functions are called, one of the function calls can easily be discarded).

void ff(int z){

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

         ...

         case 99:
         f99();
         break;

      }
     
}
The results (call f99):

Files:
test.mq4  9 kb
 
Integer:

How many different options can there be? A reasonable number? 10, 20, 100? Even with 100 choices, switch works faster than OOP.

I'd like to warn against overgeneralizations: such an effect is reasonable to expect in mql, because it uses virtual "pseudo-pointers" - essentially handles referring to the internal (hidden) hash table of real addresses. To resolve such pointers, it takes a significant amount of extra time, well beyond direct pointer addressing. I haven't measured, but it's likely that the same pointer "bottlenecking" effect will be found in dotNET languages and other similar implementations.

Languages with "real" pointers won't have this effect, switch will lose out there - the bigger the list of choices is.

So OOP has essentially nothing to do with it...

 
MetaDriver:

I'd like to warn against overgeneralization. Such an effect is reasonable to expect in mql, because it uses virtual "pseudo-pointers" - essentially hash tables that refer to the internal (hidden) hash table of real addresses. To resolve such pointers, it takes a significant amount of extra time, well beyond direct pointer addressing. I haven't measured, but it's likely that the same pointer "bottlenecking" effect will be found in dotNET languages and other similar implementations.

In languages with "real" pointers this effect won't happen, the switch will lose - the bigger the list of choices is.

So OOP has essentially nothing to do with it...

It's clear that it's just the compiler itself, hence that with "correct" compilation the execution times of the above examples would equalize.
 
icas:
It is clear that it is only a matter of the compiler itself, hence that if the above examples are compiled "correctly", the execution times will equalise.
The concept of "correctness" depends on the rules, hence it is meaningless. ;)
 

I'll point out the error straight away: f functions are empty and completely cut out by the compiler. That is, there is actually no function call. I'm also not sure what state the ff function will degenerate to and if it won't end up being inline inside the for loop, thus removing even the function call.

The virtual method, on the other hand, cannot be cut out - it is always called. As a result, in one case the loop is just spinning, and in the other case the call is in the loop.

In any tests, you must first prove their correctness, and only then go to the results.

 

Here's one with a non-empty function:

Files:
test2.mq4  11 kb
 

Here are all the functions that are unique, moreover, called via switch, more complex than a class method.

Files:
test3.mq4  12 kb
 
Integer:

Here are all the functions that are unique, moreover, called via switch, more complex than a class method.

What a mess...

Have you heard anything about inlining? What about aggressive inlining?

What usually happens to simple function bodies and what does a good optimizing compiler do with them? This isn't 1995, is it?

 
MetaDriver:

I'd like to warn against overgeneralization. Such an effect is reasonable to expect in mql, because it uses virtual "pseudo-pointers" - essentially handles referring to the internal (hidden) hash table of real addresses. To resolve such pointers, it takes a significant amount of extra time, well beyond direct pointer addressing. I haven't measured, but it's likely that the same pointer "bottlenecking" effect will be found in dotNET languages and other similar implementations.

In languages with "real" pointers there will be no such effect, there the switch will lose - the bigger the list of choices.

So OOP has essentially nothing to do with it...

Yep. Here it is in C sharp:)


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

 

Start any test by proving that it is correct and actually measures what it claims to measure.

What is presented above contains amazing mistakes and shows the author's complete lack of understanding of compilation mechanisms and how the code works.

 
Renat:

Start any test by proving that it is correct and actually measures what it claims to measure.

What is presented above contains amazing mistakes and shows the author's complete lack of understanding of compilation mechanisms and how the code works.

Why should I understand the compilation mechanisms? Just to believe that a bad result is better than a good one? It's the result that matters.
Reason: