2009-01-23 21 views
5

J'ai une application d'analyse comparative pour tester les performances de certaines API que j'ai écrites. Dans cette application de benchmarking, j'utilise essentiellement le QueryPerformanceCounter et j'obtiens le timing en divisant la différence des valeurs QPC après et avant d'appeler dans l'API, par la fréquence. Mais les résultats de l'analyse comparative semblent varier Si j'exécute l'application (même exécutable s'exécutant sur le même jeu de Dll) à partir de différents lecteurs. En outre, sur un lecteur particulier, en exécutant l'application pour la première fois, la fermeture de l'application et sa réexécution génèrent des résultats d'analyse différents. Quelqu'un peut-il expliquer ce comportement? Est-ce que j'ai râté quelque chose?L'exécution d'une application gérée pour la 2ème fois montre des performances différentes de la 1ère

Quelques informations plus utiles:

Le comportement est comme ceci: Lancez l'application, fermez et relancez à nouveau, les résultats de l'analyse comparative semble améliorer la 2ème manche et reste par la suite même. Ce comportement est plus important en cas d'exécution du lecteur C. Je voudrais également mentionner que mon application benchmark a une option pour relancer/retester une API particulière sans avoir à fermer l'application. Je comprends qu'il y a du jitting impliqué, mais ce que je ne comprends pas c'est que lors de la première exécution de l'application, quand vous relancez une API plusieurs fois sans fermer l'application, la performance se stabilise après quelques runs, puis quand vous fermez et relancez le même test, la performance semble s'améliorer.

De même, comment expliquez-vous le changement de performance lors de l'exécution de différents lecteurs?

[INFORMATION MISE A JOUR]

je l'ai fait une NGEN et maintenant la différence de performance entre les différentes pistes de même endroit est disparu. Par exemple, si j'ouvre l'application benchmark, exécutez-la une fois, fermez-la et relancez-la depuis le même emplacement, elle affiche les mêmes valeurs.

Mais j'ai rencontré un autre problème maintenant. Lorsque je lance l'application depuis le lecteur D et que je l'exécute plusieurs fois (deux itérations d'API dans le même lancement de prog), puis à partir de la troisième itération, les performances de toutes les API semblent diminuer d'environ 20% . Ensuite, si vous fermez et relancez l'application et l'exécutez, pour les deux premières itérations, elle donne des valeurs correctes (même valeur que celle obtenue à partir de C), puis de nouveau les performances tombent au-delà. Ce comportement n'est pas visible lorsqu'il est exécuté à partir du lecteur C. À partir du lecteur C, peu importe le nombre de passages que vous prenez, il est assez cohérent. J'utilise de grandes baies doubles pour tester mes performances API. J'étais inquiet que le GC entrait en jeu entre les tests donc j'appelle GC.Collect() & GC.WaitForPendingFinalizers() explicitement avant et après chaque test. Donc, je ne pense pas que cela a quelque chose à voir avec GC.

J'ai essayé d'utiliser le temps AQ pour savoir ce qui se passe à partir de la 3ème itération, mais ce qui est amusant, c'est que lorsque j'exécute l'application avec le temps AQ, la performance ne baisse pas du tout.

Le compteur de performance ne suggère aucune activité IO amusante.

Merci Niranjan

+0

Cory a répondu correctement à une question possible. Cependant, si vous pouviez détailler les résultats, cela aiderait un peu plus. Par exemple, si le deuxième passage était pire, alors c'est une histoire différente. :) – BobbyShaftoe

+0

Toutes mes excuses pour ne pas être descriptif plus tôt. Le comportement est le suivant: Lancez l'application, fermez-la et relancez-la, les résultats de l'analyse comparative semblent s'améliorer lors de la 2ème exécution et restent par la suite identiques. Ce comportement est plus important en cas d'exécution du lecteur C. –

Répondre

1

Je pense qu'il ya une combinaison d'effets ici:

Tout d'abord, en cours d'exécution la même fonction au sein du faisceau de test plusieurs fois, avec les mêmes données à chaque fois, améliorera probablement parce que:

  • JIT compilation permettra d'optimiser le code qui est exécuté le plus souvent pour améliorer les performances (comme mentioned already par Cory Foy)
  • le code du programme sera dans le cache du disque (comme mentioned already par Crashwork)
  • Une partie du code de programme dans le cache du processeur si elle est assez petit et exécuté assez souvent

Si les données sont différentes pour chaque exécution de la fonction dans le faisceau de test, cela pourrait expliquer pourquoi la fermeture et le fonctionnement le faisceau de test améliore à nouveau les résultats: les données vont maintenant aussi être dans le cache disque, où ce n'était pas la première fois. Et enfin, oui, même si deux 'disques' sont sur le même disque physique, ils auront des performances différentes: les données peuvent être lues plus rapidement depuis l'extérieur du plateau que vers l'intérieur. Si ce sont des disques physiques différents, la différence de performance semble très probable. En outre, un disque peut être plus fragmenté que l'autre, entraînant des temps de recherche plus longs et des taux de transfert de données plus lents.

3

Oui. C'est ce qu'on appelle Just-In-Time compiling. Fondamentalement, votre application est déployée en tant que MSIL (Microsoft Intermediate Language) et la première fois qu'elle est exécutée, elle est convertie en code natif.Vous pouvez toujours exécuter NGen (voir l'article ci-dessus) ou disposer d'une période de préchauffage dans vos scripts de test de performances, où il exécute plusieurs fois le scénario avant d'effectuer une analyse comparative des performances.

+0

Vraiment? Est-ce qu'il stocke réellement le code JIT entre les exécutions? De cette page Web, il ne semble pas. – paxdiablo

+0

Je pense qu'il est plus probable que les DLL soient déjà chargées en mémoire. – paxdiablo

+0

Je voudrais mentionner ici que mon application de référence a une option pour relancer/retester une API particulière sans avoir à fermer l'application. –

4

L'exécution d'une application amène son exécutable et d'autres fichiers du disque dur dans le cache disque du système d'exploitation (en RAM). Si elle est relancée peu de temps après, beaucoup de ces fichiers seront probablement encore en cache. La RAM est beaucoup plus rapide que le disque.

Et bien sûr, un disque peut être plus rapide qu'un autre.

1

D'autres facteurs entrent probablement en ligne de compte. Mise en cache du système de fichiers sur la machine, mise en mémoire tampon des données récemment utilisées, etc.

Il est préférable d'exécuter plusieurs tests (ou plusieurs centaines!) Et de faire la moyenne sur l'ensemble, sauf si vous mesurez spécifiquement les temps de démarrage à froid.