La splendeur et la pauvreté de l'OLP

 

Classe de base, plusieurs descendants, l'un des descendants est utilisé, en fonction des paramètres définis au démarrage. C'est un principe bien connu du fonctionnement du programme universel. Peu importe le nombre de variantes possibles (c'est-à-dire de classes descendantes), ce cas est censé fonctionner très rapidement car il n'y a pas d'appels if et switch pour modifier le fonctionnement du programme, il suffit que la classe descendante requise soit sélectionnée lors de l'initialisation pour que tout fonctionne de manière simple et directe.

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

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

CClass1 * cl;

void OnInit(){

   cl=new CClass1;

}

Cependant...

Combien de variantes différentes peut-il y avoir ? Un nombre raisonnable ? 10, 20, 100 ? Même avec 100 variantes, switch fonctionne plus rapidement que OOP.

Voici un script permettant de comparer les performances. Il compare la POO ci-dessus et un simple commutateur avec des fonctions (et deux fonctions sont appelées, l'un des appels de fonction peut facilement être écarté).

void ff(int z){

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

         ...

         case 99:
         f99();
         break;

      }
     
}
Les résultats (appel f99) :

Dossiers :
test.mq4  9 kb
 
Integer:

Combien d'options différentes peut-il y avoir ? Un nombre raisonnable ? 10, 20, 100 ? Même avec 100 choix, le switch fonctionne plus rapidement que le OOP.

J'aimerais mettre en garde contre les généralisations excessives : un tel effet est raisonnable dans mql, car il utilise des "pseudo-pointeurs" virtuels - essentiellement des poignées se référant à la table de hachage interne (cachée) des adresses réelles. Pour résoudre de tels pointeurs, il faut une quantité significative de temps supplémentaire, bien au-delà de l'adressage direct par pointeur. Je n'ai pas mesuré, mais il est probable que le même effet de "goulot d'étranglement" des pointeurs se retrouve dans les langages dotNET et autres implémentations similaires.

Les langages avec de "vrais" pointeurs n'auront pas cet effet, le switch y perdra - plus la liste de choix est grande.

Donc la POO n'a essentiellement rien à voir avec ça...

 
MetaDriver:

Je voudrais mettre en garde contre une généralisation excessive. Un tel effet est raisonnable dans mql, car il utilise des "pseudo-pointeurs" virtuels - essentiellement des tables de hachage qui font référence à la table de hachage interne (cachée) des adresses réelles. Pour résoudre de tels pointeurs, il faut une quantité significative de temps supplémentaire, bien au-delà de l'adressage direct par pointeur. Je n'ai pas mesuré, mais il est probable que le même effet de "goulot d'étranglement" des pointeurs se retrouve dans les langages dotNET et autres implémentations similaires.

Dans les langages avec de "vrais" pointeurs, cet effet ne se produira pas, le commutateur sera perdant - plus la liste de choix est grande.

Donc la POO n'a essentiellement rien à voir avec ça...

Il est clair qu'il s'agit du compilateur lui-même, d'où le fait qu'avec une compilation "correcte", les temps d'exécution des exemples ci-dessus seraient égaux.
 
icas:
Il est clair que ce n'est qu'une question de compilateur, donc que si les exemples ci-dessus sont compilés "correctement", les temps d'exécution seront égaux.
Le concept de "justesse" dépend des règles, il n'a donc aucun sens. ;)
 

Je vous signale tout de suite l'erreur : les fonctions f sont vides et complètement coupées par le compilateur. C'est-à-dire qu'il n'y a en fait aucun appel de fonction. Je ne sais pas non plus dans quel état la fonction ff va dégénérer et si elle ne finira pas par être en ligne à l'intérieur de la boucle for, supprimant ainsi même l'appel de fonction.

La méthode virtuelle, en revanche, ne peut être coupée - elle est toujours appelée. Par conséquent, dans un cas, la boucle ne fait que tourner, et dans l'autre cas, l'appel est dans la boucle.

Dans tous les tests, vous devez d'abord prouver leur exactitude, et seulement ensuite passer aux résultats.

 

En voici un avec une fonction non vide :

Dossiers :
test2.mq4  11 kb
 

Voici toutes les fonctions qui sont uniques, de plus, appelées via switch, plus complexes qu'une méthode de classe.

Dossiers :
test3.mq4  12 kb
 
Integer:

Voici toutes les fonctions qui sont uniques, de plus, appelées via switch, plus complexes qu'une méthode de classe.

Quel gâchis...

Avez-vous entendu parler de l'inlining ? Qu'en est-il de l'inlining agressif ?

Qu'arrive-t-il généralement aux corps de fonctions simples et que fait un bon compilateur optimisateur avec eux ? On n'est pas en 1995, n'est-ce pas ?

 
MetaDriver:

Je voudrais mettre en garde contre une généralisation excessive. Un tel effet est raisonnable dans mql, car il utilise des "pseudo-pointeurs" virtuels - essentiellement des poignées se référant à la table de hachage interne (cachée) des adresses réelles. Pour résoudre de tels pointeurs, il faut une quantité significative de temps supplémentaire, bien au-delà de l'adressage direct par pointeur. Je n'ai pas mesuré, mais il est probable que le même effet de "goulot d'étranglement" des pointeurs se retrouve dans les langages dotNET et autres implémentations similaires.

Dans les langages avec de "vrais" pointeurs, il n'y aura pas d'effet de ce genre, là le commutateur sera perdant - plus la liste de choix est grande.

Donc la POO n'a essentiellement rien à voir avec ça...

Yep. Le voici en do dièse :)


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

 

Commencez tout test en prouvant qu'il est correct et qu'il mesure réellement ce qu'il prétend mesurer.

Ce qui est présenté ci-dessus contient des erreurs étonnantes et montre le manque total de compréhension de l'auteur des mécanismes de compilation et du fonctionnement du code.

 
Renat:

Commencez tout test en prouvant qu'il est correct et qu'il mesure réellement ce qu'il prétend mesurer.

Ce qui est présenté ci-dessus contient des erreurs étonnantes et montre le manque total de compréhension de l'auteur des mécanismes de compilation et du fonctionnement du code.

Pourquoi devrais-je comprendre les mécanismes de compilation ? Juste pour croire qu'un mauvais résultat est meilleur qu'un bon ? C'est le résultat qui compte.
Raison: