Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

vitesse: if vs pointeur de methode

126 réponses
Avatar
Guillaume Desticourt
bonsoir,

je m interroge sur la vitesse d execution entre une comparaison et un
pointeur de methode.
j ai une class dont une methode peut changer de comportement au cours de
la vie du process, mais cela rarement.
je me demandais si je devais avoir une methode unique avec un bloc
if/else ou alors un pointeur de methode sette a la methode qui va bien.
j ai donc ecrit deux petits programmes de test, et la solution if/else
est /visiblement/ plus rapide.
et donc je me demandais:
- est ce que mon test est pertinent?
- pourquoi une telle difference de temps?

les prog ont ete compile sous un linux 2.6 avec g++ 3.3.5

merci,

def.hh
------


#ifndef DEF_HH
# define DEF_HH

#include <stdlib.h>

#define MAX_LOOP 1000000000

class Test;

typedef int (Test::*behavior_t)(void);

class Test
{
public:
Test() :
_test(true)
{
}

int behavior1(void)
{
return 0;
}
int behavior2()
{
return 0;
}

inline bool isTrue(void)
{
return _test;
}
private:
bool _test;
};

#endif

if.cc
-----


#include "def.hh"

int main(void)
{
Test * test = new Test();

for (unsigned long u = 0;
u < MAX_LOOP;
++u)
{
if (test->isTrue())
test->behavior1();
else
abort();
}
return 0;
}


pointer.cc
----------



#include "def.hh"

int main(void)
{
Test * test = new Test();
behavior_t behavior;
if (test->isTrue())
behavior = &Test::behavior1;
else
abort();

(test->*behavior)();


for (unsigned long u = 0;
u < MAX_LOOP;
++u)
{
(test->*behavior)();
}
return 0;
}


Makefile
--------

all: iftest pointertest

iftest: def.hh
g++ -Wall -Werror -O2 if.cc -o iftest

pointertest: def.hh
g++ -Wall -Werror -O2 pointer.cc -o pointertest

clean:
rm -f *.o
rm -f *~
rm -f iftest pointertest


une tarball est - provisoirement - disponible ici:
http://www.freenopen.net/~guillaume/info/prog/source/ifpointerbench-20050720-1755.tar.bz2

--
Guillaume Desticourt

10 réponses

1 2 3 4 5
Avatar
Fabien LE LEZ
On Wed, 20 Jul 2005 18:30:57 +0200, Guillaume Desticourt
:

- est ce que mon test est pertinent?


Est-ce que la différence sera réellement visible par l'utilisateur,
dans le programme final ?

Code de la manière la plus claire et lisible possible, et occupe-toi
des problèmes de performances si le programme final est effectivement
trop lent.

Avatar
Stan
"Fabien LE LEZ" a écrit dans le message de news:

On Wed, 20 Jul 2005 18:30:57 +0200, Guillaume Desticourt
:

- est ce que mon test est pertinent?


Est-ce que la différence sera réellement visible par l'utilisateur,
dans le programme final ?

Code de la manière la plus claire et lisible possible, et occupe-toi
des problèmes de performances si le programme final est effectivement
trop lent.



Ben oui, c'est pénible un clic de souris qui a une delai de latence
de 2 uS ;-)

--
-Stan


Avatar
Guillaume Desticourt
On Wed, 20 Jul 2005 18:30:57 +0200, Guillaume Desticourt
:


- est ce que mon test est pertinent?



Est-ce que la différence sera réellement visible par l'utilisateur,
dans le programme final ?



je ne sais pas. la en faisant un boucle de 1000000000 iterations, la
difference est visible a l oeil nu. maintenant je n ai aucune idee du
volume de donnees que mon programme aura a traiter. mais la difference
de temps d executions des deux programmes de test est tellement enorme
que je me dis qu'il doit y avoir une erreur.

Code de la manière la plus claire et lisible possible, et occupe-toi
des problèmes de performances si le programme final est effectivement
trop lent.



heu bof, je trouve plus logique de viser le resultat desire plutot
qu'appliquer des rustines et me retrouver avec un code - encore plus -
illisible. Surtout que ca se fera a coup sur beaucoup plus tard, et tout
aussi surement par quelqu'un d'autre qui ne comprendra pas mon code...

Enfin la on est limite HS vis a vis du c++ et du probleme - technique -
qui etait: pourquoi un test est plus lent qu un passage par pointeur de
fonction?

cordialement,

--
Guillaume Desticourt


Avatar
Richard Delorme
On Wed, 20 Jul 2005 18:30:57 +0200, Guillaume Desticourt
:


- est ce que mon test est pertinent?



Est-ce que la différence sera réellement visible par l'utilisateur,
dans le programme final ?

Code de la manière la plus claire et lisible possible, et occupe-toi
des problèmes de performances si le programme final est effectivement
trop lent.


Si les performances ne sont pas importantes, pourquoi diable programmer
en C++ ?

--
Richard


Avatar
Richard Delorme
bonsoir,

je m interroge sur la vitesse d execution entre une comparaison et un
pointeur de methode.


La question est donc de savoir si ça :

{
if (test->isTrue())
test->behavior1();
else
abort();
}


est plus lent que :

{
(test->*behavior)();
}


Ça me semble un peu évident non ?
Appeler une fonction (vide en plus) à travers un pointeur de fonction,
ou par la fonction elle même produit à peu près les mêmes performances.
Ajouter un autre appel de fonction (test->isTrue()) et un test
(if(...)) supplémentaire va donc logiquement réduire les performances.
Pour peu que le compilateur soit intelligent et ait supprimé l'appel à
une fonction vide, le test de performance compare une boucle vide, avec
une boucle contenant des choses...

Il n'y a que la fable qui voit la tortue devancer le lièvre.


--
Richard

Avatar
Guillaume Desticourt

bonsoir,

je m interroge sur la vitesse d execution entre une comparaison et un
pointeur de methode.



La question est donc de savoir si ça :

{
if (test->isTrue())
test->behavior1();
else
abort();
}



est plus lent que :

{
(test->*behavior)();
}



Ça me semble un peu évident non ?


oui. a moi aussi, c est pour cela que j'ai poste :)

Appeler une fonction (vide en plus) à travers un pointeur de fonction,
ou par la fonction elle même produit à peu près les mêmes performances.
Ajouter un autre appel de fonction (test->isTrue()) et un test
(if(...)) supplémentaire va donc logiquement réduire les performances.
Pour peu que le compilateur soit intelligent et ait supprimé l'appel à
une fonction vide, le test de performance compare une boucle vide, avec
une boucle contenant des choses...

Il n'y a que la fable qui voit la tortue devancer le lièvre.




Justement, a l'execution, la premiere methode (if) est plus rapide que
la deuxieme!!! mais peut etre le compilateur a t il reussi a supprimer
l'appel a la fonction vide mais pas a travers le pointeur de fonction...
je referai le test demain avec une fonction non vide, et peut etre sans
le -O2

cordialement,

--
Guillaume Desticourt


Avatar
Fabien LE LEZ
On Wed, 20 Jul 2005 20:32:41 +0200, Richard Delorme
:

Si les performances ne sont pas importantes


Je n'ai absolument pas dit ça.

Je dis juste que tenter de bidouiller, au détriment de la lisibilité
du code, et au détriment des autres fonctionnalités (le temps qu'on
passe à essayer d'optimiser là où ce n'est pas forcément nécessaire,
on ne le passe pas à implémenter autre chose) est une mauvaise idée.

Le C++ permet déjà une grande rapidité tout en codant élégamment. Si,
à l'exécution, certaines fonctionnalités se révèlent trop lentes,
alors seulement on repère (avec un profiler) les fonctions à
optimiser, et on tente de les optimiser. Mais ça n'arrive pas si
souvent que ça.

, pourquoi diable programmer en C++ ?


Le C++ a deux gros avantages :

- c'est un langage très puissant, très riche ;

- l'exécution des programmes est généralement rapide, ce qui
permet souvent de ne pas se préoccuper d'optimisation. Le raisonnement
va assez loin : si tu as quelques Mo de données, tu peux les charger
entièrement en mémoire, dans tes propres structures, plutôt que
d'utiliser un moteur externe de base de données, avec tous les
problèmes de déploiement que ça implique.

Avatar
Richard Delorme

Justement, a l'execution, la premiere methode (if) est plus rapide que
la deuxieme!!! mais peut etre le compilateur a t il reussi a supprimer
l'appel a la fonction vide mais pas a travers le pointeur de fonction...


Sans doute. Comme le test->isTrue() est toujours vrai, il l'a sans doute
supprimer aussi.

je referai le test demain avec une fonction non vide, et peut etre sans
le -O2


Regarder l'assembleur produit peut aussi aider.


--
Richard

Avatar
Richard Delorme
On Wed, 20 Jul 2005 20:32:41 +0200, Richard Delorme
:


Si les performances ne sont pas importantes



Je n'ai absolument pas dit ça.


C'est ce que je comprends.

Je dis juste que tenter de bidouiller, au détriment de la lisibilité
du code, et au détriment des autres fonctionnalités (le temps qu'on
passe à essayer d'optimiser là où ce n'est pas forcément nécessaire,
on ne le passe pas à implémenter autre chose) est une mauvaise idée.


Un truc de mon expérience personnelle : la plupart des optimisations
rendent le code plus clair. La meilleure façon d'optimiser un code c'est
de supprimer du code inutile, et moins il y a de code, plus c'est clair.
Par exemple, enlever un test toujours vrai (donc inutile) rend le code
plus lisible et plus rapide. Et avec la quantité de code que je vois
passer et qui contient toutes sortes de choses inutiles : variables
redondantes, calculs inutilisés par la suite, etc. il y a de quoi optimiser.

Le C++ permet déjà une grande rapidité tout en codant élégamment. Si,
à l'exécution, certaines fonctionnalités se révèlent trop lentes,
alors seulement on repère (avec un profiler) les fonctions à
optimiser, et on tente de les optimiser. Mais ça n'arrive pas si
souvent que ça.


Le souvent dépend du domaine d'application.


, pourquoi diable programmer en C++ ?



Le C++ a deux gros avantages :

- c'est un langage très puissant, très riche ;


Je ne trouve pas justement. Des langages comme Java, Python, Ruby, etc
dont beaucoup plus riches et supportent plein de fonctionnalité
nativement (multi-threads, graphismes, réseau, ramasse-miette, etc.) et
à mon avis, on code beaucoup plus élégamment et rapidement avec eux
qu'en C++. Par contre leurs performances sont lamentables...


- l'exécution des programmes est généralement rapide, ce qui
permet souvent de ne pas se préoccuper d'optimisation.


Mon raisonnement, est que, comme le C++ produit un code rapide, le
besoin de performances peu justifier sont choix. Et ce critère oblige
aussi à se préoccuper d'optimisation.


Le raisonnement
va assez loin : si tu as quelques Mo de données, tu peux les charger
entièrement en mémoire, dans tes propres structures, plutôt que
d'utiliser un moteur externe de base de données, avec tous les
problèmes de déploiement que ça implique.


Ce n'est pas un exemple d'optimisation ça ?

--
Richard


Avatar
Matthieu Moy
Guillaume Desticourt writes:

inline bool isTrue(void)
^^^^^^

{
return _test;
}


Il est là à mon avis, ton problème. Met cette fonction dans un .cpp
inaccessible au compilo quand il compile le bout de code que tu veux
benchmarquer, et met cet appel dans les deux bouts de codes que tu
testes (l'un dans le if(...), l'autre n'importe ou vu que le compilo
ne pourra pas savoir si il y a un effet de bord).

Si tu veux benchmarquer X Vs Y, il faut qu'il n'y ai que X et Y qui
changent ...

--
Matthieu

1 2 3 4 5