Pracht und Armut der PLO

 

Basisklasse, mehrere Nachkommen, einer der Nachkommen wird verwendet, je nach den beim Start festgelegten Parametern. Dies ist ein bekanntes Prinzip der universellen Programmarbeit. Es spielt keine Rolle, wie viele Varianten es geben kann (d.h. Nachfolgeklassen), dieser Fall soll sehr schnell funktionieren, weil es keine if- und switch-Aufrufe gibt, die die Arbeitsweise des Programms verändern, sondern nur einmal die gewünschte Nachfolgeklasse bei der Initialisierung ausgewählt wird und dann alles ganz einfach funktioniert.

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

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

CClass1 * cl;

void OnInit(){

   cl=new CClass1;

}

Aber...

Wie viele verschiedene Varianten kann es geben? Eine vernünftige Zahl? 10, 20, 100? Selbst bei 100 Varianten arbeitet Switch schneller als OOP.

Hier ist ein Skript für den Leistungsvergleich. Sie vergleicht die obige OOP mit einem einfachen Schalter mit Funktionen (und zwei Funktionen werden aufgerufen, einer der Funktionsaufrufe kann leicht verworfen werden).

void ff(int z){

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

         ...

         case 99:
         f99();
         break;

      }
     
}
Die Ergebnisse (Aufruf f99):

Dateien:
test.mq4  9 kb
 
Integer:

Wie viele verschiedene Optionen kann es geben? Eine vernünftige Zahl? 10, 20, 100? Selbst bei 100 Auswahlmöglichkeiten arbeitet Switch schneller als OOP.

Ich möchte vor übermäßigen Verallgemeinerungen warnen: Ein solcher Effekt ist in mql durchaus zu erwarten, da es virtuelle "Pseudo-Zeiger" verwendet - im Wesentlichen Handles, die auf die interne (versteckte) Hash-Tabelle mit echten Adressen verweisen. Um solche Zeiger aufzulösen, ist ein erheblicher zusätzlicher Zeitaufwand erforderlich, der weit über die direkte Zeigeradressierung hinausgeht. Ich habe keine Messungen vorgenommen, aber es ist wahrscheinlich, dass derselbe "Engpass"-Effekt bei Zeigern auch in dotNET-Sprachen und anderen ähnlichen Implementierungen auftritt.

Sprachen mit "echten" Zeigern haben diesen Effekt nicht, der Schalter verliert dort - je größer die Liste der Auswahlmöglichkeiten ist.

OOP hat also im Grunde nichts damit zu tun...

 
MetaDriver:

Ich möchte vor einer Überverallgemeinerung warnen: Ein solcher Effekt ist in mql durchaus zu erwarten, da es virtuelle "Pseudo-Zeiger" verwendet - im Wesentlichen Hash-Tabellen, die auf die interne (versteckte) Hash-Tabelle der realen Adressen verweisen. Um solche Zeiger aufzulösen, ist ein erheblicher zusätzlicher Zeitaufwand erforderlich, der weit über die direkte Zeigeradressierung hinausgeht. Ich habe keine Messungen vorgenommen, aber es ist wahrscheinlich, dass derselbe "Engpass"-Effekt bei Zeigern auch in dotNET-Sprachen und anderen ähnlichen Implementierungen auftritt.

In Sprachen mit "echten" Zeigern wird dieser Effekt nicht eintreten, der Schalter wird dort verlieren - je größer die Liste der Auswahlmöglichkeiten ist.

OOP hat also im Grunde nichts damit zu tun...

Es ist klar, dass es nur am Compiler selbst liegt, so dass sich bei "korrekter" Kompilierung die Ausführungszeiten der obigen Beispiele angleichen würden.
 
icas:
Es ist klar, dass dies nur eine Frage des Compilers ist, d.h. wenn die obigen Beispiele "richtig" kompiliert werden, gleichen sich die Ausführungszeiten an.
Das Konzept der "Korrektheit" hängt von den Regeln ab und ist daher bedeutungslos. ;)
 

Ich weise gleich auf den Fehler hin: f-Funktionen sind leer und werden vom Compiler komplett herausgeschnitten. Das heißt, es gibt eigentlich keinen Funktionsaufruf. Ich bin mir auch nicht sicher, in welchen Zustand die ff-Funktion ausartet und ob sie nicht am Ende innerhalb der for-Schleife inline sein wird, wodurch sogar der Funktionsaufruf entfällt.

Die virtuelle Methode hingegen kann nicht ausgeschaltet werden - sie wird immer aufgerufen. Dies hat zur Folge, dass sich in einem Fall die Schleife nur dreht und im anderen Fall der Aufruf in der Schleife steht.

Bei allen Tests müssen Sie zunächst deren Richtigkeit nachweisen und erst dann zu den Ergebnissen kommen.

 

Hier ist eine mit einer nicht leeren Funktion:

Dateien:
test2.mq4  11 kb
 

Hier sind alle Funktionen, die einzigartig sind, außerdem über switch aufgerufen werden, komplexer als eine Klassenmethode.

Dateien:
test3.mq4  12 kb
 
Integer:

Hier sind alle Funktionen, die einzigartig sind, außerdem über switch aufgerufen werden, komplexer als eine Klassenmethode.

Was für ein Chaos...

Haben Sie schon einmal etwas über Inlining gehört? Was ist mit aggressivem Inlining?

Was passiert normalerweise mit einfachen Funktionskörpern und was macht ein guter Optimierungscompiler mit ihnen? Wir haben nicht mehr 1995, oder?

 
MetaDriver:

Ich möchte vor einer Übergeneralisierung warnen: Ein solcher Effekt ist in mql durchaus zu erwarten, da es virtuelle "Pseudo-Zeiger" verwendet - im Wesentlichen Handles, die auf die interne (versteckte) Hash-Tabelle mit realen Adressen verweisen. Um solche Zeiger aufzulösen, ist ein erheblicher zusätzlicher Zeitaufwand erforderlich, der weit über die direkte Zeigeradressierung hinausgeht. Ich habe keine Messungen vorgenommen, aber es ist wahrscheinlich, dass derselbe "Engpass"-Effekt bei Zeigern auch in dotNET-Sprachen und anderen ähnlichen Implementierungen auftritt.

In Sprachen mit "echten" Zeigern gibt es diesen Effekt nicht, dort verliert der Schalter - je größer die Liste der Auswahlmöglichkeiten ist.

OOP hat also im Grunde nichts damit zu tun...

Ja. Hier ist es in Cis:)


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

 

Beginnen Sie jeden Test mit dem Nachweis, dass er korrekt ist und tatsächlich das misst, was er zu messen vorgibt.

Die obige Darstellung enthält erstaunliche Fehler und zeigt, dass der Autor keine Ahnung von Kompilierungsmechanismen und der Funktionsweise des Codes hat.

 
Renat:

Beginnen Sie jeden Test mit dem Nachweis, dass er korrekt ist und tatsächlich das misst, was er zu messen vorgibt.

Die obige Darstellung enthält erstaunliche Fehler und zeigt, dass der Autor keine Ahnung von Kompilierungsmechanismen und der Funktionsweise des Codes hat.

Warum sollte ich die Kompilierungsmechanismen verstehen? Nur um zu glauben, dass ein schlechtes Ergebnis besser ist als ein gutes? Es ist das Ergebnis, das zählt.
Grund der Beschwerde: