Características del lenguaje mql5, sutilezas y técnicas - página 84

 
Alain Verleyen:

¿Puede proporcionar el código de referencia para demostrarlo?

#define  BENCH(A)                                                              \
{                                                                             \
  const ulong StartTime = GetMicrosecondCount();                              \
  A;                                                                          \
  Print("Time[" + #A + "] = " + (string)(GetMicrosecondCount() - StartTime)); \
}

double Bench1( const int Size, const string Str )
{
  double Tmp = 0;
  
  for (int i = 0; i < Size; i++)
    Tmp += (double)Str;

  return(Tmp);
}

double Bench2( const int Size, const string Str )
{
  double Tmp = 0;;
  
  for (int i = 0; i < Size; i++)
    Tmp += StringToDouble(Str);

  return(Tmp);
}

double Bench3( const int Size, const string Str )
{
  double Tmp = 0;
  
  for (int i = 0; i < Size; i++)
    Tmp += StringToDouble2(Str); // https://www.mql5.com/ru/forum/170952/page83#comment_7121066

  return(Tmp);
}

void OnStart()
{  
  const string Str = "123.456";
  
  BENCH(Print(Bench1(1 e7, Str)));
  BENCH(Print(Bench2(1 e7, Str)));
  BENCH(Print(Bench3(1 e7, Str)));
}


Resultado(liberación)

1234559999.924436
Time[Print(Bench1(1 e7,Str))] = 1656182
1234559999.924436
Time[Print(Bench2(1 e7,Str))] = 1639179
1234559999.924436
Time[Print(Bench3(1 e7,Str))] = 147382


Y esto es lo que se obtiene cuando se ejecuta en modo de perfilado

1234559999.924436
Time[Print(Bench1(1 e7,Str))] = 1757705
1234559999.924436
Time[Print(Bench2(1 e7,Str))] = 1877177
1234559999.924436
Time[Print(Bench3(1 e7,Str))] = 4578266

Lamentablemente, en este caso no se puede confiar en el perfilador.

 
fxsaber:


Resultado ( Liberación )


HH Y esto es lo que obtengo, si lo ejecuto en modo de perfilado

No sólo es imposible confiar en el perfilador en este caso, sino que Bench1 se ejecuta 10 veces más rápido que en la versión de lanzamiento.

Gracias por eso.

Resultado ( Liberación )

Time [Bench1( 1 e7,Str)] = 1680754
Time [Bench2( 1 e7,Str)] = 1646789
Time [Bench3( 1 e7,Str)] = 143408     more then 10 times faster !!! 

Probado con el Asesor Experto por estrategia.

2018.04.16 14:24:28.049    Core 1    OnTester result 39725470 (µs bench1)
2018.04.16 14:26:14.629    Core 1    OnTester result 39270950 (µs bench2)
2018.04.16 14:27:13.566    Core 1    OnTester result 20467067 (µs bench3)

Otras 2 veces más rápido (pero no más de 10 veces, lo que seguramente se debe a la optimización del compilador).

Archivos adjuntos:
170952.mq5  6 kb
 
Alain Verleyen:

Probado con un asesor de estrategia.

2018.04.16 14:24:28.049    Core 1    OnTester result 39725470 (µs bench1)
2018.04.16 14:26:14.629    Core 1    OnTester result 39270950 (µs bench2)
2018.04.16 14:27:13.566    Core 1    OnTester result 20467067 (µs bench3)

Es 2 veces más rápido todavía (pero no más de 10 veces más rápido, lo que obviamente se debe a la optimización del compilador).

Se mide el tiempo que queda para generar ticks, no sólo el cálculo de OnTick.

Aquí está sólo la medida OnTick

#define  PROFILER_OnTick // Замеряет чистое время выполнения всех OnTick - немного замедляет общую работу
#include <TesterBenchmark.mqh> // https://www.mql5.com/ru/code/18804

input int bench=1;// between 1 and 3

void OnTick()
{
  static const string Str = "123.456";

  switch(bench)
  {
    // https://www.mql5.com/ru/forum/170952/page84#comment_7121207
    case 1 : Bench1(1, Str); break;
    case 2 : Bench2(1, Str); break;
    case 3 : Bench3(1, Str); break;
  }  
}


Banco1

i = 0 Pass = 0 OnTester = 3.729 s.: OnTick Profiler: Count = 7197033, Interval = 1.895 s., 3796990.9 unit/sec , Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795
i = 1 Pass = 1 OnTester = 3.843 s.: OnTick Profiler: Count = 7197033, Interval = 1.950 s., 3690523.1 unit/sec , Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795


Banco3

i = 0 Pass = 0 OnTester = 2.280 s.: OnTick Profiler: Count = 7197033, Interval = 0.631 s., 11404799.6 unit/sec , Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795
i = 1 Pass = 1 OnTester = 2.340 s.: OnTick Profiler: Count = 7197033, Interval = 0.640 s., 11242184.6 unit/sec , Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795


Por un factor de tres. No se puede ser 10 veces más rápido por las múltiples llamadas a la función BenchX. StringToDouble2 en sí es 10 veces más rápido.

 
fxsaber:

Se mide el tiempo todavía para generar ticks, no sólo para calcular OnTick.

...

Tienes razón.

Realmente me sorprende que sea 10 veces más rápido, pero su función sólo se puede utilizar cuando se sabe que la cadena contiene un valor doble válido.

2018.04.16 17: 14: 16.183 170952_180416 (EURUSD, H1) StringToDouble2 (abcdef) = 5456784.0

 
Aleksey Vyazmikin:

Gracias, pero este script también guarda incorrectamente.

En mi monitor, la limitación en el lado derecho está marcada con una línea vertical, y la captura de pantalla está mucho más allá de esa línea.

Permítanme citar la respuesta de servicedesk:

En este caso, la ayuda de ChartScreenShot debe tomarse literalmente

align_mode=ALIGN_RIGHT

[en] Modo de una salida de pantalla estrecha. El valor de la enumeración ENUM_ALIGN_MODE. ALIGN_RIGHT indica la alineación al borde derecho (salida desde el final). ALIGN_LEFT especifica la alineación a la izquierda.

Significa que cuando se especifica la alineación ALIGN_RIGHT el gráfico se desplazará forzosamente hacia el borde derecho, lo que equivale a ejecutar el comando

ChartNavigate(0,CHART_END,0);

Este comportamiento se estableció hace muchos años (así que históricamente) cuando todavía no existía la función ChartNavigate(). Si se establece align_mode=ALIGN_RIGHT se garantiza que se eliminará exactamente el borde derecho del gráfico.

Cuando se añadió la función ChartNavigate(), el comportamiento de la función ChartScreenShot no cambió.

Por lo tanto, si desea obtener el efecto deseado (el gráfico no se desplazará hacia el borde derecho), utilice el valor ALIGN_LEFT para el parámetro align_mode.

 
Alain Verleyen:

su función sólo puede utilizarse cuando se sabe que la cadena contiene un valor doble válido.

2018.04.16 17: 14: 16.183 170952_180416 (EURUSD, H1) StringToDouble2 (abcdef) = 5456784.0

Arreglado, ahora funciona como el original

#define  PRINT(A) Print(#A + " = " + (string)(A))

void OnStart()
{    
  const string Str[] = {"123.456", "-asdf1234", "12as", ".34 a", "..23", "1.."};

  for (int i = 0; i < ArraySize(Str); i++)
  {
    PRINT(Str[i]);
    
    PRINT((double)Str[i]);
    PRINT(StringToDouble2(Str[i])); // https://www.mql5.com/ru/forum/170952/page83#comment_7121066
    
    Print("");
  }
}
 

Si elimina la const resaltada, el tiempo de ejecución de la función se duplicará. Esto demuestra que el compilador no siempre crea un código óptimo y necesita este tipo de pistas.

 
fxsaber:

Si eliminamos la const marcada, el tiempo de ejecución de la función se duplicará. Indica que el compilador no siempre crea un código óptimo y necesita este tipo de pistas.

Interesante, gracias.

Por favor, no edites tu código cuando ya hayas recibido una respuesta, no recibí la notificación de que lo habías actualizado.

 
fxsaber:

Si eliminamos la const marcada, el tiempo de ejecución de la función se duplicará. Indica que el compilador no siempre crea un código óptimo y necesita este tipo de pistas.

Muy interesante...
¿Alguna idea de por qué ocurre esto?

¿Cuál es el mecanismo?

 

Para determinar la anchura de una captura de pantalla tomada con MQL5 que incluya todas las barras de un determinado periodo, se ofrece la siguiente solución.

Una peculiaridad resultó ser el hecho de que la anchura de la captura de pantalla tiene que ser corregida en diferentes aproximaciones del gráfico.

Los "coeficientes" reales resultaron ser diferentes (para mí específicamente) para la variante con y sin la escala.

 if (Use_Shakala==false)
 
 {
   ChartSetInteger(0,CHART_SHOW_PRICE_SCALE ,0);//Показывать или нет ценовую шкалу
   int TotalPixel=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);   // Ширина графика в пикселях
   int WidthBar=int(1<<ChartGetInteger(0,CHART_SCALE));            // сколько пикселей между барами
   int FirstBar=(int)ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR);   // номер первого (левого) бара на экране
   int VisibleBars=(int)ChartGetInteger(0,CHART_VISIBLE_BARS);     // количество видимых баров на экране
   int BarNr= FirstBar-(Shift_Start-Shift_Stop)*(-1);              // номер искомого бара, допустим на 12 баров правее самого левого бара 
   int LeftPixelOfBar=((FirstBar-BarNr)>=VisibleBars || FirstBar<BarNr)?(-1):((FirstBar-BarNr)*WidthBar);  // левый пиксель искомого бара, если бара нет на экране тогда -1
   int RightPixelOfBar =(LeftPixelOfBar<0)?(-1):LeftPixelOfBar+WidthBar-1;                                 //правый пиксель искомого бара, если бара нет на экране тогда -1
   if (RightPixelOfBar>=TotalPixel) RightPixelOfBar=TotalPixel-1;  // проверяем не за пределами ли экрана 

      if (Zoom==0)ZoomX=6;
      if (Zoom==1)ZoomX=5;
      if (Zoom==2)ZoomX=5;
      if (Zoom==3)ZoomX=4;
      if (Zoom==4)ZoomX=2;
      if (Zoom==5)ZoomX=0;

  pp=WidthBar*((Shift_Start-Shift_Stop)*(-1)+2)+ZoomX;
}

  if (Use_Shakala==true)
  {
   ChartSetInteger(0,CHART_SHOW_PRICE_SCALE ,1);//Показывать или нет ценовую шкалу
   int TotalPixel=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);   // Ширина графика в пикселях
   int WidthBar=int(1<<ChartGetInteger(0,CHART_SCALE));            // сколько пикселей между барами
   int FirstBar=(int)ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR);   // номер первого (левого) бара на экране
   int VisibleBars=(int)ChartGetInteger(0,CHART_WIDTH_IN_BARS);     // количество видимых баров на экране
   int BarNr= FirstBar-(Shift_Start-Shift_Stop)*(-1);              // номер искомого бара, допустим на 12 баров правее самого левого бара 
   int LeftPixelOfBar=((FirstBar-BarNr)>=VisibleBars || FirstBar<BarNr)?(-1):((FirstBar-BarNr)*WidthBar);  // левый пиксель искомого бара, если бара нет на экране тогда -1
   int RightPixelOfBar =(LeftPixelOfBar<0)?(-1):LeftPixelOfBar+WidthBar-1;                                 //правый пиксель искомого бара, если бара нет на экране тогда -1
   if (RightPixelOfBar>=TotalPixel) RightPixelOfBar=TotalPixel-1;  // проверяем не за пределами ли экрана 

      if (Zoom==0)ZoomX=1;
      if (Zoom==1)ZoomX=1;
      if (Zoom==2)ZoomX=1;
      if (Zoom==3)ZoomX=3;
      if (Zoom==4)ZoomX=2;
      if (Zoom==5)ZoomX=0;    
  pp=WidthBar*((Shift_Start-Shift_Stop)*(-1)+2-0.5)+ZoomX+Schkala;
  
  }
//pp 		 - ширина скриншота
//Shift_Start    - номер левого бара, который целиком должен попасть на скрин
//Shift_Stop     - номер правого бара, который целиком должен попасть на скрин
//Schkala        - ширина цифровой шкалы по методу fxsaber
//Zoom           - степень приближение экрана
Razón de la queja: