UNE CLASSE SIMPLE EN C++ POUR MESURER LE TEMPS D'EXECUTION D'UNE PORTION DE CODE

DeAtHCrAsH Messages postés 2670 Date d'inscription vendredi 25 janvier 2002 Statut Membre Dernière intervention 6 février 2013 - 15 sept. 2005 à 11:28
bweps Messages postés 17 Date d'inscription dimanche 12 décembre 2004 Statut Membre Dernière intervention 10 mai 2007 - 10 juin 2008 à 13:50
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/33788-une-classe-simple-en-c-pour-mesurer-le-temps-d-execution-d-une-portion-de-code-sur-une-machine-non-dediee-aux-tests-windows

bweps Messages postés 17 Date d'inscription dimanche 12 décembre 2004 Statut Membre Dernière intervention 10 mai 2007
10 juin 2008 à 13:50
Bonjour Shuttleur,

je ne connais pas l'explication a priori. Cependant, cela pourrait être une de ces raisons (simples hypothèses) :
- le déroulement des fonctions que vous appelez est sensible au temps (une fonction prépare le terrain pour une deuxième ; si celle-ci ne s'exécute pas immédiatement (en cas de basculement vers un autre thread...), des opérations supplémentaires sont nécessaires pour l'exécution de la seconde. J'opterais pour cette hypothèse dans le cas de la manipulation d'objets OLE ; je n'ai aucune idée de comment les interactions sont gérées mais cela me semble plausible : durant la période ou le thread chronométré est suspendu, d'autres processus ou threads peuvent modifier l'état d'un objet OLE. A la reprise du thread, l'objet est signalé comme modifié, et la récupération du nouvel état de l'objet doit être effectuée par notre thread (d'où la consommation CPU). Lorsqu'aucun sleep n'est appelé, l'ensemble des fonctions est exécuté intégralement dans "intervalle inter-tick" (puisque le temps mesuré est nul), et aucun thread extérieur ne peut modifier l'objet partagé.

- lors de l'appel à Sleep (ou lors du réveil du thread), il semblerait qu'il puisse y avoir un petit délai dû au fait que le temps de "sommeil" ne soit pas proportionnel au "clock tick rate" (http://msdn.microsoft.com/en-us/library/ms686298(VS.85).aspx). Ceci pourrait peut-être expliquer une augmentation du temps mesuré de quelques millisecondes par appel à sleep, au cas où ces cas soient gérés approximativement par le système (serait surprenant ?).
shuttleur Messages postés 33 Date d'inscription mercredi 12 septembre 2007 Statut Membre Dernière intervention 30 juin 2008
10 juin 2008 à 09:35
Salut Bweps

Je n'ai pas trop compris pourquoi il y a eu si peu d'engouement pour votre source, je la trouve très pratique.

Dans la pratique, j'ai des résultats étonnants : j'obtiens 0 ms pour l'exécution de plusieurs fonctions (dont des appels à une interface OLE), et si j'insère dans cette liste de fonctions exécutées un Sleep(500), j'obtiens des valeurs entre 70 et 90 ms.

J'ai essayé d'utiliser SetThreadAffinityMask(GetCurrentThread(),1) qui est nécessaire pour que certains chronomètres de ce site fonctionnent bien (bride l'appli à un coeur) mais rien ne change.

J'utilise simplement : tps->iGo() et j'affiche tps->iStop()

Sinon, le chronomètre renvoie une valeur plausible à un seul endroit de mon code.

Auriez vous une explication ?
(Vista + Core2Duo)
cs_baot Messages postés 1 Date d'inscription lundi 17 décembre 2007 Statut Membre Dernière intervention 25 janvier 2008
25 janv. 2008 à 17:47
rien à dire sur tout ce qui dit bweps, c'est le meilleur, c'est mon petit frère...
bweps Messages postés 17 Date d'inscription dimanche 12 décembre 2004 Statut Membre Dernière intervention 10 mai 2007
12 avril 2007 à 12:22
Bonjour,
a priori vous pouvez utiliser la même méthode dans n'importe quel langage sous Windows, à partir du moment où celui-ci vous permet d'appeler des fonctions de l'API Windows (GetCurrentProcess et GetProcessTimes ici).
Bon courage.
saulcy25 Messages postés 1 Date d'inscription jeudi 13 avril 2006 Statut Membre Dernière intervention 3 avril 2007
3 avril 2007 à 14:00
Bonjour , je trouve trés interessant ce que vous avez fait ,moi je cherche à clalculer le temps d'éxecution d'un fonction en temps réel sans en prendre en compte de ce qu'elle fait windows en c#
est ce que vous croyer que je peux utiliser votre téchnique.
Cordialement
yann_lo_san Messages postés 1137 Date d'inscription lundi 17 novembre 2003 Statut Membre Dernière intervention 23 janvier 2016 26
5 oct. 2006 à 15:20
J'aime bien ta façon de partager le code BWEPS, sans pour autant avoir l'espoir de se faire mousser par les candidats aux jugements en tout genres, moi je te mets 10/10 et je te dis bravo !
bweps Messages postés 17 Date d'inscription dimanche 12 décembre 2004 Statut Membre Dernière intervention 10 mai 2007
6 oct. 2005 à 15:14
Voici un cas dans lequel j'en ai besoin (ça n'engage que moi) : je dois tester la robustesse d'un algorithme. Pour cela, je dois le lancer sur au moins 500 jeux de test différents et contrôler que le temps d'exécution est "stable", i.e. qu'il n'y ai pas d'instances pour lesquelles l'algo met deux fois plus de temps que pour les autres.
Comme je ne dispose que de ma machine de développement pour effectuer les tests et que je n'ai pas les droits d'admin dessus, la seule solution que j'ai trouvé est de lancer ces tests la nuit ou le week-end, et ne conserver que le temps de mon processus pour ne pas fausser les mesures. Du coup, si l'antivirus se met en route, je ne me retrouve pas avec quelques instances 10 fois "plus lentes" que les autres alors qu'elles sont "aussi faciles" que les autres.
Voilà. Si quelqu'un a une autre solution à me proposer, je suis prêt à changer de méthode si elle me paraît meilleure.
nightlord666 Messages postés 746 Date d'inscription vendredi 17 juin 2005 Statut Membre Dernière intervention 23 mai 2007 10
5 oct. 2005 à 22:03
Je rappelle quand même à bweps que la plupart du temps, on chroonmètre une fonction pour connaitre le temps qu'elle va mettre à s'executer sur N'IMPORTE QUEL ordinateur, pas avec un seul processus.
Enfin, je ne critique pas ta source, car j'ai bien appris en l'examinant, mais je trouve que ça ne sert pas à grand chose...
En fait, je t'ai mis 7 pour ta source.
bweps Messages postés 17 Date d'inscription dimanche 12 décembre 2004 Statut Membre Dernière intervention 10 mai 2007
19 sept. 2005 à 15:55
ok.j'avions pas compris. :)
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
19 sept. 2005 à 15:06
Je pense que le post de DeAtHCrAsH relevait de la simple boutade, pas de quoi se prendre le crane pour si peu. Plaisanter entre 2 algos ne fait jamais de mal.
bweps Messages postés 17 Date d'inscription dimanche 12 décembre 2004 Statut Membre Dernière intervention 10 mai 2007
19 sept. 2005 à 14:41
DeAtHCrAsH, je te rappelle que l'intérêt principal (que vous ne semblez pas saisir sur ce forum tant que vos "pontes" ne vous ont pas ouvert les yeux sur la voie de la sagesse) est d'avoir une mesure du TEMPS CONSACRE A L'EXECUTION DU PROCESSUS, ce que GetTickCount est incapable de faire.
Maintenant, s'il est impossible aux trois quarts des visiteurs de ce forum de se faire leur opinion sans avoir à appeler leur maman pour leur expliquer et ne faire que l'écouter (il semble que tu n'aies pas vraiment lu mes posts, mais seulement ceux de BruNews, dont je ne remets pas en cause l'incommensurable sagesse, mais son côté Gourou), il me semble que le côté mutualisation des connaissances qui devrait se développer sur un forum est fortement bridé ici par votre manie (que j'ai pu découvrir en parcourant d'autres posts du forum) de suivre les opinions de quelques rares éclairés. De ce fait, si l'éclairé en personne ne voit pas l'intérêt de quelque chose qu'il n'aura jamais à utiliser, vous non plus, alors que vous ne travaillez pas forcément dans les mêmes conditions ni ne faîtes exactement la même chose que lui. Précisément, ici, BruNews peut mesurer ses temps d'exécution avec n'importe quelle méthode puisqu'il dispose de machines consacrées, au moins dans certaines circonstances, exclusivement aux test. Ce n'est pas mon cas, et, je pense, pas le cas de beaucoup de programmeurs solo, amateur, "à petit budget" ou perdu dans une plus ou moins grosse boîte dont l'administrateur système a décidé de ne pas céder les droits nécessaire à la gestion de l'antivirus ou d'autres logiciels de maintenance. Ceux-ci pourraient alors profiter de mon expérience s'ils ne se contentaient pas de l'avis d'une unique personne, qui n'a pas certainement pas eu le temps dans sa vie d'humain d'expérimenter la totalité des conditions de travail possibles.
J'espère sincèrement m'être trompé et que l'idée porteuse de ce forum n'est pas totalement gâché par ce genre de comportements.
DeAtHCrAsH Messages postés 2670 Date d'inscription vendredi 25 janvier 2002 Statut Membre Dernière intervention 6 février 2013
17 sept. 2005 à 01:43
Quote : "on obtiendrait +- la même précision avec simplement GetTickCount."

-> En gros BWEPS c'est pris la tete pour rien
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
15 sept. 2005 à 22:35
On s'est très bien compris, pour cela que je disais qu'il ne faut pas de switch context.
Le compteur haute précision est le même pour tout le monde et unique dans le système. Ceci ne me semble pas grave, les mesures en millièmes de secondes ne se font qu'en phase de tests et sur machines de dev, on sait au moment des mesures qu'on ne lance pas d'autres trucs pour ne pas fausser les mesures.
GetProcessTimes reste un bon choix pour des routines plus longues, encore que on obtiendrait +- la même précision avec simplement GetTickCount.
bweps Messages postés 17 Date d'inscription dimanche 12 décembre 2004 Statut Membre Dernière intervention 10 mai 2007
15 sept. 2005 à 19:12
Hmm... On ne se comprend pas (ou du moins je ne te comprends pas).
Le compteur dont tu parles est-il lié au système "globalement" ou au processus ou thread qui fait appelle QueryPerformanceCounter?
Si le compteur est global, la mesure peut être faussée par l'utilisation du système par d'autres appli qui tournent en même temps, et le temps calculé n'est pas celui de notre code, mais celui de notre code plus tous les autres qui peuvent être amenés à s'exécuter dans un environnement multi-tâche comme Windows. S'il faut recourir à des astuces (pas très recommandables) comme définir la priorité du thread en Critical, avoue que ma méthode est, sinon moins précise, bien plus pratique !
Est-ce que j'ai bien exprimé ce qui me fait poser ma question précédente ?
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
15 sept. 2005 à 18:07
Il n'est pas notion de processus dans cette affaire, chaque appel QueryPerformanceCounter enregistre le compteur au moment de l'appel et rien de plus. Il faut bien sur éviter tout switch context pendant les mesures, à cet effet utiliser SetThreadPriority,SetThreadIdealProcessor, etc...
bweps Messages postés 17 Date d'inscription dimanche 12 décembre 2004 Statut Membre Dernière intervention 10 mai 2007
15 sept. 2005 à 17:59
J'ai regardé très succinctement la doc de msdn sur QueryPerformanceFrequency et QueryPerformanceCounter et je n'ai pas trouvé la réponse à cette question : est-ce que ces procédures renvoient le temps "global" ou le temps CPU du processus (utilité première de GetProcessTimes)?
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
15 sept. 2005 à 17:34
J'ai testé cela:

DWORD v = 0;

__int64 __stdcall Teste1()
{
LARGE_INTEGER lif, lid, lie;
DWORD i, n;
QueryPerformanceFrequency(&lif);
n = 0;
i = 0xFFFFFFF;
QueryPerformanceCounter(&lid);
do {
n += i;
} while(--i);
v = n;
QueryPerformanceCounter(&lie);
lie.QuadPart -= lid.QuadPart;
lie.QuadPart *= 1000;
lie.QuadPart /= lif.QuadPart;
return lie.QuadPart;
}

__int64 __stdcall Teste2()
{
FILETIME a;
__int64 deb, fin;
DWORD i, n;
HANDLE hprcss;
hprcss = GetCurrentProcess();
n = 0;
i = 0xFFFFFFF;
GetProcessTimes(hprcss, &a, &a, &a, (FILETIME*) &deb);
do {
n += i;
} while(--i);
v = n;
GetProcessTimes(hprcss, &a, &a, &a, (FILETIME*) &fin);
fin -= deb;
fin /= 10000;
return fin;
}

int WINAPI WinMain(HINSTANCE h, HINSTANCE x, LPSTR ystr, int z)
{
char buf[24];
_i64toa(Teste1(), buf, 10);
MessageBox(0, buf, "1", 0);
_i64toa(Teste2(), buf, 10);
MessageBox(0, buf, "2", 0);
return 0;
}

GetProcessTimes n'a bien sur pas la précision du timer haute résolution, normal ce n'est pas fait pour cela mais ça reste acceptable sur des routine un peu longues.
Pas la peine d'avoir 3 FILETIME inutilisées, 1 seule suffit.
Pour celles de début et fin, du __int64 fera l'affaire et évitera plein de calculs.
bweps Messages postés 17 Date d'inscription dimanche 12 décembre 2004 Statut Membre Dernière intervention 10 mai 2007
15 sept. 2005 à 15:55
La précision supportée par la structure FILETIME est de 100 nanosecondes. Cependant, la mesure effectuée par GetProcessTimes() n'est bien sûr pas aussi précise et semble renvoyer, dans les cas de figure où je l'utilise, des sommes de 15 ou 16ms. Sur des temps de moins de 200ms., cela ne suffit donc pas. Par contre, au-dessus de cette valeur, cela me convient personnellement, les algorithmes que je teste (théorie des graphes, de l'ordonnancement...) étant très gourmands en temps.
Pour ce qui est de la compatibilité, GetProcessTimes peut être utilisée sous Windows "Longhorn", Windows XP, Windows 2000 Professional, Windows NT Workstation 3.5 et plus récents.
bweps Messages postés 17 Date d'inscription dimanche 12 décembre 2004 Statut Membre Dernière intervention 10 mai 2007
15 sept. 2005 à 15:00
En effet, on pourrait gagner en efficacité ici.
Je ne me suis pas attardé sur la complexité temporelle de cette procédure, qui est négligeable par rapport à celle des procédures dont je mesure le temps d'exécution. Mais si on doit faire un usage très intensif de la méthode (pour mesurer de très petit temps d'exécution de nombreuses fois), elle peut représenter pas mal de perte, et la modif que tu proposes est judicieuse.
Merci pour le feed-back.
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
15 sept. 2005 à 11:48
GetProcessTimes() est très bien pour ce genre de chose.
Par contre:
int ms=-(stUser1.wMilliseconds +1000*(stUser1.wSecond+60*(stUser1.wMinute+60*(stUser1.wHour+24*(stUser1.wDay-1)))))
+ stUser2.wMilliseconds +1000*(stUser2.wSecond+60*(stUser2.wMinute+60*(stUser2.wHour+24*(stUser2.wDay-1))));

Pourquoi ce double calcul ??? soustraire le filetime final à celui de début et on ne fait qu'1 seule fois le calcul.
DeAtHCrAsH Messages postés 2670 Date d'inscription vendredi 25 janvier 2002 Statut Membre Dernière intervention 6 février 2013
15 sept. 2005 à 11:28
Est ce que c'est vraiment précis ?
Je ne connaissais pas cette méthode.

BruNews aurais tu peux etre plus d'information la dessus?
Rejoignez-nous