Question

Certaines des plates-formes sur lesquelles je développe ne disposent pas d'outils de profilage. Je recherche des suggestions / techniques que vous avez personnellement utilisées pour vous aider à identifier les points chauds, sans recourir à un profileur.

Le langage cible est le C ++.

Je m'intéresse à ce que vous avez personnellement utilisé.

Était-ce utile?

La solution

J'ai trouvé ce qui suit plutôt utile:

#ifdef PROFILING
# define PROFILE_CALL(x) do{ \
    const DWORD t1 = timeGetTime(); \
    x; \
    const DWORD t2 = timeGetTime(); \
    std::cout << "Call to '" << #x << "' took " << (t2 - t1) << " ms.\n"; \
  }while(false)
#else
# define PROFILE_CALL(x) x
#endif

Ce qui peut être utilisé dans la fonction appelante en tant que telle:

PROFILE_CALL(renderSlow(world));
int r = 0;
PROFILE_CALL(r = readPacketSize());

Autres conseils

Pas de blague: En plus de transférer les timings vers std :: cout et d'autres approches orientées texte / données, j'utilise également la fonction Beep (). Il y a quelque chose à propos d'entendre l'écart de silence entre deux "Beep". points de contrôle qui font une impression différente.

C'est comme la différence entre regarder une partition écrite et écouter la musique. C'est comme la différence entre lire rgb (255,0,0) et voir le feu rouge des moteurs de pompiers.

Donc, à l’heure actuelle, j’ai une application client / serveur et des signaux sonores de fréquences différentes indiquant où le client envoie le message, où le serveur commence sa réponse, termine sa réponse, où la réponse entre pour la première fois chez le client, etc. Je peux très naturellement avoir une idée de l'endroit où le temps est passé.

En gros, si un outil de profilage n'est pas disponible, vous imitez ce que le profileur aurait fait. Vous insérez des compteurs dans des fonctions que vous jugez intéressantes et comptez le nombre de fois et éventuellement la taille / le type d'arguments utilisés.

Si vous avez accès à des minuteries sur votre plate-forme, vous pouvez les démarrer / les arrêter au début / à la fin desdites fonctions pour obtenir également des informations sur l'heure d'exécution, si cela ne ressort pas clairement du code. Cela vous donnera le meilleur rendement en termes de code complexe, car il y aura généralement trop de fonctions pour les instrumenter. Au lieu de cela, vous pouvez obtenir le temps passé dans certaines sections de code en dédiant une minuterie à chacune d’elles.

Ces deux techniques combinées peuvent former une approche itérative, dans laquelle vous trouvez la grande section de code qui consomme la majorité de vos cycles à l'aide de minuteries, puis instrumentez des fonctions individuelles avec une granularité plus fine pour cibler le problème.

S'il s'agit de quelque chose d'assez long (par exemple une minute ou plus), j'exécute le logiciel dans un débogueur, puis je le répare plusieurs fois et je vois où se trouve le débogueur, cela donne une idée très approximative de l'état du logiciel. à (par exemple si vous cassez 10 fois et qu'ils sont tous au même endroit, cela vous dit quelque chose d'intéressant!). Très rugueux et prêt, mais ne nécessite aucun outil, instrumentation, etc.

Je ne sais pas trop quelles plates-formes vous aviez à l'esprit, mais sur les microcontrôleurs intégrés, il est parfois utile de modifier une ligne de sortie numérique et de mesurer la durée de l'impulsion à l'aide d'un oscilloscope, d'un compteur / temporisateur ou d'un analyseur logique.

J'utiliserais la règle des 80/20 et placerais des minuteries autour des points chauds ou des chemins d'appels intéressants. Vous devriez avoir une idée générale de l'emplacement des goulots d'étranglement (ou du moins de la majorité des chemins d'exécution) et utiliser le minuteur haute résolution approprié à la plate-forme approprié (QueryPerformanceCounters, gettimeofday, etc.).

Habituellement, je ne me préoccupe de rien au démarrage ou à l'arrêt (sauf si nécessaire) et j'aurai des "points d'étranglement" bien définis, généralement des messages transmis ou une sorte de calcul algorithmique. J'ai généralement constaté que les messages sinks / srcs (sinks moreso), les files d'attente, les mutex et tout simplement les problèmes (algorithmes, boucles) représentent généralement la majeure partie de la latence d'un chemin d'exécution.

Utilisez-vous Visual Studio?

Vous pouvez utiliser les commutateurs / Gh et / GH. Voici un exemple impliquant l'inspection de pile

Ces indicateurs vous permettent, fichier par fichier, d’enregistrer les fonctions non décorées appelées chaque fois qu’une méthode est entrée et / ou laissée au moment de l’exécution.

Vous pouvez ensuite enregistrer à tout moment les informations de profilage, pas uniquement les informations de minutage. Les empilements, l'adresse d'appel, l'adresse de retour, etc. Ce qui est important, car vous voudrez peut-être savoir que la fonction X a utilisé Y fois sous la fonction Z et pas seulement le temps total passé dans la fonction X.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top