À propos du profileur de code MT5 - page 3

 

En guise de suivi :


Laquelle des lignes (1, 2 ou 3) est encore gourmande en ressources ?

Je n'arrive pas à comprendre comment le "lourd" iTime, qui prend 55% du temps de tout le programme, n'affiche que 0,81% de Self CPU ?
Et vice versa - pourquoi la parenthèse d'ouverture (1) et la condition la plus simple (2, vraie très rarement) affichent-elles 33,84% d'autocontrôle ?

Pourquoi le CPU personnel et le CPU total ne correspondent pas ?


La fonction est vraiment lourde, mais toute sa lourdeur est située plus bas dans le code. Et le profileur suggère de chercher un remplacement pour iTime et deux variables booléennes !

Il y a quelque chose que je ne comprends pas.

 
Andrey Khatimlianskii:

Il y a quelque chose que je ne comprends pas.

Un glissement peut-être ?

 
Andrei Trukhanovich:

Un glissement peut-être ?

Il n'en a pas l'air, les chiffres du rapport sont les mêmes.

 
Andrey Khatimlianskii:

Ilyas, aide-moi à comprendre ça aussi.

1. Pourquoi un appel de fonction vide peut prendre 34,5% du Self CPU ? Dans le même temps, l'appel de la fonction qui le suit, dont les éléments internes occupent 38,16 % de la CPU totale, n'apparaît pas du tout dans le rapport ?


Code de fonction :



2. Cet exemple montre le deuxième problème : la ligne avec TimeCurrent() prend un temps déraisonnable non seulement dans la fonction mais dans le programme en général :

Avant que je ne commente le corps de CheckTimeSeries(), la charge principale se trouvait sur sa ligne TimeCurrent().

Est-ce vraiment une fonction si lourde ? Par quoi le remplacer ? Ou comment le rendre économique (mise en cache dans une seule boucle d'exécution du programme) ?

Chaque fois que je le peux, j'économise les calculs en les diluant (une fois par barre, une fois toutes les X secondes, une fois toutes les Y ms, etc.) Mais il s'avère que la vérification elle-même, qu'il s'agisse de faire les calculs, est assez gourmande en ressources.


Merci pour votre aide.

1) Sans code, il est difficile de dire pourquoi ces statistiques sont si mauvaises, peut-être à cause de l'optimisation.

2) Pourquoi ne pas essayer de récupérer le temps dans la fonction Timer, avant la boucle et le passer en paramètre plus loin, à quoi bon appeler cette fonction au moins 2*N fois dans la boucle ?

 
Andrey Khatimlianskii:

En guise de suivi :


Laquelle des lignes (1, 2 ou 3) est encore gourmande en ressources ?

Je n'arrive pas à comprendre comment le "lourd" iTime, qui prend 55% du temps de tout le programme, n'affiche que 0,81% de Self CPU ?
Et vice versa - pourquoi la parenthèse d'ouverture (1) et la condition la plus simple (2, vraie très rarement) affichent-elles 33,84% d'autocontrôle ?

Pourquoi le CPU personnel et le CPU total ne correspondent-ils pas ?


La fonction est vraiment lourde, mais toute sa lourdeur est située plus bas dans le code. Et le profileur suggère de chercher un remplacement pour iTime et deux variables booléennes !

Il y a quelque chose que je ne comprends pas.

1) Je vais supposer que la fonction a été inlined

2) Les compteurs ne sont vraiment pas liés, SelfCPU est la charge sur le code de la fonction, sans tenir compte des fonctions appelées, dans le code donné, c'est un ouvreur IF (branching)

3) Le compteur TotalCPU indique la charge de la branche d'exécution, pour tous les appels dans cette branche du programme.

 

Ne devrait-il pas toujours être de 100% ? Ou même un peu moins, en considérant également les @global_initializations et @global_deinitializations.

Voici plus de 102% ...(Build 3003 sur les données historiques).

 
Ilyas :

1) Je vais supposer que la fonction a été inlined

2) Les compteurs ne sont vraiment pas liés, SelfCPU est la charge sur le code de la fonction, sans tenir compte des fonctions appelées, dans le code ci-dessus, c'est un ouvreur IF (branchement)

3) Le compteur TotalCPU indique la charge d'une branche d'exécution, pour tous les appels dans cette branche du programme.

Quelle est son utilité ? De toute évidence, l'instruction IF en elle-même a une faible charge CPU. Ne devrait-il pas inclure les appels de fonction ?

Dans tous les cas. Comment comprendre (à partir de l'exemple d'Andrew) :

if(!simulated) taking 3.86% ?!?

Qu'est-ce que c'est que ça ?


où nous semblons être dans la même fonction Tick () !

Je veux vraiment utiliser Profiler et le comprendre, mais rien de tout cela n'a de sens. Désolé.

Que faire ? Comment pouvons-nous vous aider ?

 
Ilyas:

1) Sans code, il est difficile de dire pourquoi les statistiques sont si mauvaises, peut-être à cause de l'optimisation.

2) Pourquoi ne pas essayer de récupérer le temps dans la fonction Timer avant la boucle et le passer en paramètre plus loin, quel est l'intérêt d'appeler cette fonction au moins 2*N fois dans la boucle ?

Merci pour les réponses !

1) Je peux difficilement le reproduire sur un code simple, oui. Et je ne suis pas prêt à dévoiler tout le projet.

2) Dans ce cas particulier, je suis d'accord.

Mais il existe de nombreuses autres classes qui utilisent le même contrôle ou un contrôle similaire et qui ne peuvent se passer de TimeCurrent ou de GetTickCount.
Comment optimiser leur appel pour ne pas demander plusieurs fois la même valeur ?

Et TimeCurrent est-il vraiment si lourd, qu'il peut être perceptible en arrière-plan de calculs très lourds (même s'ils sont effectués toutes les 1 ou 5 minutes) ?
Ou est-ce que je me suis encore trompé et que 38,16% de l'unité centrale totale / 26,07% de l'unité centrale personnelle ont été occupés par la vérification de if lui-même (sans tenir compte de l'appel de la fonctionTimeCurrent) ? Mais pourquoi en est-il ainsi ?


Ilyas:

1) Je vais supposer que la fonction était en ligne

2) Les compteurs ne sont vraiment pas liés, SelfCPU est la charge sur le code de la fonction, sans tenir compte des fonctions appelées, dans le code ci-dessus, c'est l'ouvreur IF (branchement)

3) Le compteur TotalCPU montre la charge d'une branche d'exécution, par tous les appels dans cette branche du programme.

1) Il n'est pas utile de comprendre pourquoi une parenthèse ouvrante aussi vorace. Comment interpréter cela ?

2) La question du SelfCPU est maintenant claire, merci. C'est une charge de code de fonction sans tenir compte des fonctions appelées.

Cela explique également le faible niveau de SelfCPU de la chaîne avec iTime - il était très rarement atteint, il était juste rarement appelé.

Mais pourquoi un TotalCPU aussi important ? Ou bien il montre la charge de toutes les fonctions iTime (et autres fonctions CopyXXX ?) dans l'ensemble du programme ?

 
Andrey Khatimlianskii:

Merci pour vos réponses !

1) Je ne pense pas pouvoir le reproduire sur un code simple, oui. Et je ne suis pas prêt à dévoiler tout le projet.

2) Dans ce cas particulier, je suis d'accord.

Mais il existe de nombreuses autres classes qui utilisent le même contrôle ou un contrôle similaire et qui ne peuvent se passer de TimeCurrent ou de GetTickCount.
Comment optimiser leur appel pour ne pas demander plusieurs fois la même valeur ?

Et TimeCurrent est-il vraiment si lourd, qu'il peut être perceptible en arrière-plan de calculs très lourds (même s'ils sont effectués toutes les 1 ou 5 minutes) ?
Ou peut-être que je me suis encore trompé et que 38,16% du CPU total / 26,07% du CPU personnel ont été occupés par la vérification elle-même (sans appel de la fonctionTimeCurrent) ? Mais alors, pourquoi en est-il ainsi ?


1) Il n'est pas utile de comprendre pourquoi une parenthèse ouvrante aussi vorace. Comment interpréter cela ?

2) La question du SelfCPU est maintenant claire, merci. C'est une charge de code de fonction sans tenir compte des fonctions appelées.

Cela explique également le faible niveau de SelfCPU de la chaîne avec iTime - il était très rarement atteint, il était juste rarement appelé.

Mais pourquoi un TotalCPU aussi important ? Ou bien il montre la charge de toutes les fonctions iTime (et autres fonctions CopyXXX ?) dans tout le programme ?

Prenez n'importe quel code de la livraison standard, relisez-le et posez des questions sur la base de ce code, s'il vous plaît. Cela permettra d'évaluer la situation de manière reproductible et de fournir des réponses précises.

Sinon, il ne sert à rien de répondre à de petits morceaux de votre code pour les rapports du profileur. Il y a une énorme quantité de travail d'optimisation en coulisse, qui transforme tout votre code en une représentation complètement différente, mélangée et intégrée.


À titre d'information : Dieu nous préserve qu'un programmeur C++ sur 100 puisse utiliser le profileur et comprendre ses rapports. C'est la faute de l'optimiseur de code natif.

 
Alain Verleyen:

Dans tous les cas. Comment comprendre (à partir de l'exemple d'Andrew) :

if(!simulated) taking 3.86% ?!?

Oui, sans tenir compte des appels de fonctions externes, SelfCPU n'est pas très informatif. Ce n'est qu'au niveau le plus bas, où les fonctions MQL natives sont utilisées, que vous verrez la charge réelle.
Mais dans ce cas, on ne saura pas clairement à partir de quels endroits ces fonctions sont appelées plus souvent (et consomment plus), et à partir desquels il y a des appels uniques ! Quel est l'intérêt pour moi de savoir que les fonctions CopyXXX et OrderXXX consomment le plus de temps ? J'ai besoin de savoir à partir de quelles parties de mon programme ils sont appelés trop souvent/ineffectivement.

Je suppose que c'est à ça que sert le mode en conjonction avec TotalCPU. Je vais m'en occuper. Mais jusqu'à présent, je vois même des lignes complètement commentées ( !).

Raison: