Acerca del perfilador de código de MT5 - página 3

 

Como seguimiento:


¿Cuál de las líneas (1, 2 o 3) sigue siendo intensiva en recursos?

No puedo entender cómo el "pesado" iTime, que ocupa el 55% del tiempo de todo el programa, sólo muestra un 0,81% de auto CPU?
Y viceversa - ¿por qué el paréntesis de apertura (1) y la condición más simple (2, verdadera muy raramente) muestran un 33,84% de auto CPU?

¿Por qué no coinciden la CPU propia y la CPU total?


La función es realmente pesada, pero toda su pesadez se encuentra más abajo en el código. ¿Y el perfilador sugiere buscar un reemplazo para iTime y dos variables booleanas?

Es evidente que no entiendo algo.

 
Andrey Khatimlianskii:

Es evidente que me falta algo.

¿Resbalones, tal vez?

 
Andrei Trukhanovich:

¿Resbalones, tal vez?

No lo parece, las cifras del informe son las mismas.

 
Andrey Khatimlianskii:

Ilyas, ayúdame a resolver esto también.

1. ¿Por qué una llamada a una función vacía puede ocupar el 34,5% de la CPU propia? Al mismo tiempo, la llamada de la función que le sigue, cuyos internos ocupan el 38,16% del total de la CPU, no aparece en el informe en absoluto...


Código de función:



2. Este ejemplo muestra el segundo problema: la línea con TimeCurrent() tarda un tiempo excesivo no sólo dentro de la función sino en el programa en general:

Antes de comentar el cuerpo de CheckTimeSeries(), la carga principal estaba en su línea TimeCurrent().

¿Es realmente una función tan pesada? ¿Con qué sustituirlo? ¿O cómo hacer que sea económico (caché dentro de un bucle de ejecución del programa)?

Siempre que puedo, me ahorro los cálculos adelgazándolos (una vez por barra, una vez cada X segundos, una vez cada Y ms, etc.). Pero resulta que la comprobación en sí, ya sea para hacer los cálculos, consume bastantes recursos.


Gracias por la ayuda.

1) Sin código es difícil decir por qué estas estadísticas son tan malas, tal vez debido a la optimización

2) ¿Por qué no intentar obtener el tiempo en la función Timer, antes del bucle y pasarlo como parámetro más adelante, qué sentido tiene llamar a esta función al menos 2*N veces en el bucle?

 
Andrey Khatimlianskii:

Como seguimiento:


¿Cuál de las líneas (1, 2 o 3) sigue siendo intensiva en recursos?

No puedo entender cómo el "pesado" iTime, que ocupa el 55% del tiempo de todo el programa, sólo muestra un 0,81% de auto CPU?
Y viceversa - ¿por qué el paréntesis de apertura (1) y la condición más simple (2, verdadera muy raramente) muestran un 33,84% de auto CPU?

¿Por qué no coinciden la CPU propia y la CPU total?


La función es realmente pesada, pero toda su pesadez se encuentra más abajo en el código. ¿Y el perfilador sugiere buscar un reemplazo para iTime y dos variables booleanas?

Es evidente que no entiendo algo.

1) Asumiré que la función ha sido inlineada

2) Los contadores realmente no están relacionados, SelfCPU es la carga en el código de la función, sin tener en cuenta las funciones llamadas, en el código dado, es un abridor IF (ramificación)

3) El contador TotalCPU muestra la carga de la rama de ejecución, para todas las llamadas en esta rama del programa

 

¿No debería ser siempre el 100%? O incluso algo menos, teniendo en cuenta también @global_initializations y @global_deinitializations.

Aquí es más del 102% ...(Construir 3003 en los datos históricos).

 
Ilyas :

1) Asumiré que la función ha sido inlineada

2) Los contadores realmente no están relacionados, SelfCPU es la carga en el código de la función, sin tener en cuenta las funciones llamadas, en el código anterior, es un abridor IF (ramificación)

3) El contador TotalCPU muestra la carga de una rama de ejecución, para todas las llamadas en esta rama del programa.

¿Qué utilidad tiene? Obviamente, la sentencia IF por sí misma tiene una baja carga de CPU. ¿No debería incluir las llamadas a las funciones?

En cualquier caso. Cómo entender (a partir del ejemplo de Andrew):

if(!simulated) taking 3.86% ?!?

¿Qué hay de esto?


¡donde parece que estamos en la misma función Tick ()!

Realmente quiero usar Profiler y entenderlo, pero nada de esto tiene sentido. Lo siento.

¿Qué hacer? ¿Cómo podemos ayudar?

 
Ilyas:

1) Sin código es difícil decir por qué las estadísticas son tan malas, tal vez sea por la optimización

2) ¿Por qué no intentar obtener el tiempo en la función Timer antes del bucle y pasarlo como parámetro más adelante, qué sentido tiene llamar a esta función al menos 2*N veces en el bucle?

Gracias por las respuestas.

1) Apenas puedo reproducirlo en un código simple, sí. Y no estoy dispuesta a dar todo el proyecto.

2) En este caso concreto estoy de acuerdo.

Pero hay muchas otras clases que utilizan la misma comprobación o una similar y no pueden prescindir de TimeCurrent o GetTickCount.
¿Cómo optimizar su llamada para que no solicite el mismo valor varias veces?

¿Y es TimeCurrent realmente tan pesado como para que se note en el fondo de cálculos realmente pesados (aunque se realice una vez cada 1 o 5 minutos)?
¿O me equivoqué de nuevo y el 38,16% de la CPU total / el 26,07% de la CPU propia fue ocupado por la comprobación del propio if (sin considerar la llamada a la funciónTimeCurrent)? Pero, ¿por qué es así?


Ilyas:

1) Asumiré que la función era inline

2) Los contadores realmente no están relacionados, SelfCPU es la carga en el código de la función, sin tener en cuenta las funciones llamadas, en el código anterior, es el abridor IF (ramificación)

3) El contador TotalCPU muestra la carga de una rama de ejecución, por todas las llamadas en esta rama del programa

1) No ayuda a entender el porqué de un paréntesis inicial tan voraz. ¿Cómo interpretar esto?

2) Lo de SelfCPU ya está claro, gracias. Es una carga de código de funciones sin tener en cuenta las funciones que se llaman.

Esto también explica el bajo AutoCPU de la cadena con iTime - se alcanzó muy raramente, sólo se llamó raramente.

Pero, ¿por qué un TotalCPU tan grande? ¿O muestra la carga de todas las funciones iTime (y otras funciones CopyXXX?) en todo el programa?

 
Andrey Khatimlianskii:

Gracias por sus respuestas.

1) No creo que pueda reproducirlo en código simple, sí. Y no estoy dispuesta a dar todo el proyecto.

2) En este caso concreto, estoy de acuerdo.

Pero hay muchas otras clases que utilizan la misma comprobación o una similar y no pueden prescindir de TimeCurrent o GetTickCount.
¿Cómo optimizar su llamada para que no solicite el mismo valor varias veces?

¿Y es TimeCurrent realmente tan pesado, que puede notarse en el fondo de cálculos realmente pesados (incluso si se realiza cada 1 o 5 minutos)?
¿O tal vez me he equivocado de nuevo y el 38,16% de la CPU total / el 26,07% de la CPU propia estaba ocupado por la propia comprobación (sin la llamada a la funciónTimeCurrent)? Pero entonces, ¿por qué es así?


1) No ayuda a entender el porqué de un paréntesis inicial tan voraz. ¿Cómo interpretar esto?

2) Lo de SelfCPU ya está claro, gracias. Es una carga de código de funciones sin tener en cuenta las funciones que se llaman.

Esto también explica el bajo AutoCPU de la cadena con iTime - se alcanzó muy raramente, sólo se llamó raramente.

Pero, ¿por qué un TotalCPU tan grande? ¿O muestra la carga de todas las funciones iTime (y otras funciones CopyXXX?) en todo el programa?

Tome cualquier código de la entrega estándar, revíselo y haga preguntas en base a él, por favor. Esto permitirá una evaluación reproducible de la situación y proporcionará respuestas precisas.

De lo contrario, no sirve de nada responder a pequeños trozos de su código para los informes del perfilador. Hay una enorme cantidad de trabajo de optimización entre bastidores, que convierte todo tu código en una representación completamente diferente, desordenada e incrustada.


A título informativo: Dios quiera que 1 de cada 100 programadores de C++ pueda utilizar el perfilador y entender sus informes. Es culpa del optimizador de código nativo.

 
Alain Verleyen:

En cualquier caso. Cómo entender (a partir del ejemplo de Andrew):

if(!simulated) taking 3.86% ?!?

Sí, sin tener en cuenta las llamadas a funciones externas SelfCPU no es muy informativo. Sólo en el nivel más bajo, donde se utilizan las funciones MQL nativas, se verá la carga real.
Pero en este caso no quedará claro desde qué lugares se llama a estas funciones con más frecuencia (y consumen más), y desde cuáles hay llamadas únicas. ¿Para qué me sirve saber que las funciones CopyXXX y OrderXXX son las que más tiempo consumen? Necesito saber desde qué trozos de mi programa se les llama con demasiada frecuencia/ineficacia.

Supongo que para eso está el modo , combinado con TotalCPU. Lo investigaré. Pero hasta ahora veo que hay líneas completamente comentadas (¡!).