Informazioni sul profilatore di codice MT5 - pagina 3

 

Come follow-up:


Quale delle linee (1, 2 o 3) è ancora ad alta intensità di risorse?

Non riesco a capire come il "pesante" iTime, che prende il 55% del tempo di tutto il programma, mostra solo lo 0,81% di Self CPU?
E viceversa - perché la parentesi di apertura (1) e la condizione più semplice (2, vera molto raramente) mostrano il 33,84% di Self CPU?

Perché Self CPU e Total CPU non corrispondono?


La funzione è davvero pesante, ma tutta la sua pesantezza si trova più in basso nel codice. E il profiler suggerisce di cercare un sostituto per iTime e due variabili booleane?!

Evidentemente non capisco qualcosa.

 
Andrey Khatimlianskii:

Evidentemente non capisco qualcosa.

Scivolare forse?

 
Andrei Trukhanovich:

Scivolare forse?

Non sembra, le cifre del rapporto sono le stesse.

 
Andrey Khatimlianskii:

Ilyas, aiutami a capire anche questo.

1. Perché una chiamata di funzione vuota può richiedere il 34,5% della CPU di Self? Allo stesso tempo, la chiamata della funzione che la segue, i cui interni occupano il 38,16% della CPU totale, non appare affatto nel rapporto?


Codice di funzione:



2. Questo esempio mostra il secondo problema: la linea con TimeCurrent() impiega un tempo irragionevolmente lungo non solo all'interno della funzione ma nel programma in generale:

Prima di commentare il corpo di CheckTimeSeries(), il carico principale era sulla sua linea TimeCurrent().

È davvero una funzione così pesante? Con cosa sostituirlo? O come renderlo economico (caching all'interno di un ciclo di esecuzione del programma)?

Ovunque posso, risparmio i calcoli diluendoli (una volta per barra, una volta ogni X secondi, una volta ogni Y ms, ecc.) Ma si scopre che il controllo stesso, se per fare i calcoli, è abbastanza intensivo in termini di risorse.


Grazie per l'aiuto.

1) Senza codice è difficile dire perché queste statistiche sono così brutte, forse a causa dell'ottimizzazione

2) Perché non cercare di ottenere il tempo nella funzione Timer, prima del ciclo e passarlo come parametro più avanti, che senso ha chiamare questa funzione almeno 2*N volte nel ciclo?

 
Andrey Khatimlianskii:

Come follow-up:


Quale delle linee (1, 2 o 3) è ancora ad alta intensità di risorse?

Non riesco a capire come il "pesante" iTime, che prende il 55% del tempo di tutto il programma, mostra solo lo 0,81% di Self CPU?
E viceversa - perché la parentesi di apertura (1) e la condizione più semplice (2, vera molto raramente) mostrano il 33,84% di Self CPU?

Perché Self CPU e Total CPU non corrispondono?


La funzione è davvero pesante, ma tutta la sua pesantezza si trova più in basso nel codice. E il profiler suggerisce di cercare un sostituto per iTime e due variabili booleane?!

Evidentemente non capisco qualcosa.

1) Presumo che la funzione sia stata inlineata

2) I contatori non sono realmente correlati, SelfCPU è il carico sul codice della funzione, senza tener conto delle funzioni chiamate, nel codice dato, è un'apertura IF (branching)

3) Il contatore TotalCPU mostra il carico del ramo di esecuzione, per tutte le chiamate in questo ramo del programma

 

Non dovrebbe essere sempre il 100%? O anche un po' meno, considerando anche @global_initializations e @global_deinitializations.

Qui è più del 102% ...(Build 3003 su dati storici).

 
Ilyas :

1) Presumo che la funzione sia stata inlineata

2) I contatori non sono realmente correlati, SelfCPU è il carico sul codice della funzione, senza tener conto delle funzioni chiamate, nel codice di cui sopra, è un'apertura IF (branching)

3) Il contatore TotalCPU mostra il carico di un ramo di esecuzione, per tutte le chiamate in questo ramo del programma.

In che modo è utile? Ovviamente, l'istruzione IF da sola ha un basso carico di CPU. Non dovrebbe includere le chiamate di funzione?

In ogni caso. Come capire (dall'esempio di Andrew):

if(!simulated) taking 3.86% ?!?

Che mi dici di questo?


dove sembra che siamo nella stessa funzione Tick ()!

Voglio davvero usare Profiler e capirlo, ma niente di tutto questo ha senso. Mi dispiace.

Cosa fare? Come possiamo aiutare?

 
Ilyas:

1) Senza codice è difficile dire perché le statistiche sono così male, forse è a causa dell'ottimizzazione

2) Perché non cercare di ottenere il tempo nella funzione Timer prima del ciclo e passarlo come parametro più avanti, che senso ha chiamare questa funzione almeno 2*N volte nel ciclo?

Grazie per le risposte!

1) Difficilmente posso riprodurlo su un codice semplice, sì. E non sono pronto a dare via l'intero progetto.

2) In questo caso particolare sono d'accordo.

Ma ci sono molte altre classi che usano lo stesso o simile controllo e non possono fare a meno di TimeCurrent o GetTickCount.
Come ottimizzare la loro chiamata per non richiedere lo stesso valore più volte?

E TimeCurrent è davvero così pesante, che può essere notato sullo sfondo di calcoli davvero pesanti (anche se eseguiti ogni 1 o 5 minuti)?
O mi sono sbagliato di nuovo e il 38,16% della CPU totale / 26,07% della CPU Self era occupato dal controllo del se stesso (senza la chiamata alla funzioneTimeCurrent)? Ma perché è così?


Ilyas:

1) Presumo che la funzione fosse inline

2) I contatori non sono davvero correlati, SelfCPU è il carico sul codice della funzione, senza tenere conto delle funzioni chiamate, nel codice sopra, è l'apertura IF (branching)

3) Il contatore TotalCPU mostra il carico di un ramo di esecuzione, da tutte le chiamate in questo ramo del programma

1) Non aiuta a capire il perché di una parentesi di apertura così vorace. Come interpretare questo?

2) Su SelfCPU è ora chiaro, grazie. È un carico di codice di funzioni senza tener conto delle funzioni che vengono chiamate.

Questo spiega anche il basso SelfCPU della stringa con iTime - è stato raggiunto molto raramente, è stato chiamato solo raramente.

Ma perché un TotalCPU così grande? O mostra il carico di tutte le funzioni iTime (e altre funzioni CopyXXX?) nell'intero programma?

 
Andrey Khatimlianskii:

Grazie per le vostre risposte!

1) Non credo di poterlo riprodurre su un codice semplice, sì. E non sono pronto a dare via l'intero progetto.

2) In questo caso particolare, sono d'accordo.

Ma ci sono molte altre classi che usano lo stesso o simile controllo e non possono fare a meno di TimeCurrent o GetTickCount.
Come ottimizzare la loro chiamata per non richiedere lo stesso valore più volte?

E TimeCurrent è davvero così pesante, che può essere notato sullo sfondo di calcoli davvero pesanti (anche se eseguiti ogni 1 o 5 minuti)?
O forse mi sono sbagliato di nuovo e il 38,16% della CPU totale / 26,07% della CPU Self era occupato dal controllo stesso (senza la chiamata alla funzioneTimeCurrent)? Ma allora perché è così?


1) Non aiuta a capire il perché di una parentesi di apertura così vorace. Come interpretare questo?

2) Su SelfCPU è ora chiaro, grazie. È un carico di codice di funzioni senza tener conto delle funzioni che vengono chiamate.

Questo spiega anche il basso SelfCPU della stringa con iTime - è stato raggiunto molto raramente, è stato chiamato solo raramente.

Ma perché TotalCPU è così alto? O mostra il carico di tutte le funzioni iTime (e altre funzioni CopyXXX?) nell'intero programma?

Prendete qualsiasi codice dalla consegna standard, correggetelo e fate domande basate su di esso, per favore. Questo permetterà una valutazione riproducibile della situazione e fornirà risposte accurate.

Altrimenti è inutile rispondere a piccoli pezzi del vostro codice per i rapporti del profiler. C'è un'enorme quantità di lavoro di ottimizzazione dietro le quinte, che trasforma tutto il vostro codice in una rappresentazione completamente diversa, confusa e incorporata.


Per informazione: Dio non voglia che 1 programmatore C++ su 100 possa usare il profiler e capire i suoi rapporti. È colpa dell'ottimizzatore di codice nativo.

 
Alain Verleyen:

In ogni caso. Come capire (dall'esempio di Andrew):

if(!simulated) taking 3.86% ?!?

Sì, senza considerare le chiamate di funzioni esterne SelfCPU non è molto informativo. Solo al livello più basso, dove si usano le funzioni MQL native, si vedrà il carico reale.
Ma in questo caso non sarà chiaro da quali posti queste funzioni sono chiamate più spesso (e consumano di più), e da quali ci sono chiamate singole! Che senso ha sapere che le funzioni CopyXXX e OrderXXX consumano più tempo? Ho bisogno di sapere da quali pezzi del mio programma sono chiamati troppo spesso/inefficientemente.

Immagino che sia a questo che serve la modalità insieme a TotalCPU. Ci darò un'occhiata. Ma finora vedo che ci sono anche linee completamente commentate (!).