Preguntas sobre POO en MQL5 - página 87

 
Vladimir Simakov:
Pregunta. ¿Por qué necesitas un acordeón? Si en un método, una clase, en el caballo esférico, sí, en el vacío físico (bueno, me he quedado sin aliento)))), entonces sí, tiene sentido. Y si en un proyecto real, o bien una clase a nivel global, o bien un solitario que maneje todo este trichomudin (perdón por el bourbon))))) extra al principio del manejador, y, solicitar directamente de él en cualquier lugar))

es un gestor de clases que distribuye tareas y obtiene resultados de un pequeño rebaño de clases subordinadas ))))

en general, es difícil explicar de forma sobria

pero la pregunta es relevante - cómo se realiza el direccionamiento de los campos comunes cuando se leen los valores de estos campos desde diferentes métodos y muy a menudo

 
Igor Makanu:

es un gestor de clases que distribuye tareas y obtiene resultados de un pequeño rebaño de clases subordinadas ))))

en general, es difícil explicar de forma sobria

pero la pregunta es relevante - cómo se realiza el direccionamiento de los campos comunes cuando se leen los valores de estos campos desde diferentes métodos y muy a menudo

Mira. Al principio del manejador, no importa cuál, se inicia gSomeGlobal.SomeEvent(...), o, si es único, Alone::SomeEvent(...), en este método se hace el manejo de estado requerido y, luego, simplemente se solicitan los datos requeridos a través de los getters. Mientras no seas un scalper de alta frecuencia, puedes joder a todos los defensores de la velocidad, aunque aquí no hay una sobrecarga especial))
 
Vladimir Simakov:
Véase también. Al principio del manejador, no importa cuál, se inicia gSomeGlobal.SomeEvent(...), o, si es único, Alone::SomeEvent(...), en este método se hace el procesamiento de estado requerido y, luego, sólo se solicitan los datos requeridos a través de los getters. Mientras no seas un scalper de alta frecuencia, puedes joder a todos los defensores de la velocidad, aunque aquí no hay una sobrecarga especial))

el rendimiento de mt5 es suficiente para 10500 órdenes por segundo, el canal habría sido suficiente

La verdad es que tenía que comprobarlo... si quieres hacer algo, hazlo tú mismo! )))

#property copyright "IgorM"
#property link      "https://www.mql5.com/ru/users/igorm"
#property version   "1.00"

#define  TST_COUNT 1 e10

#define    SpeedTest(count,msg,EX)   {uint mss=GetTickCount(); ulong lim = count; for(ulong cnt=0;cnt<lim&&!_StopFlag;cnt++){EX;} \
                                    printf("%s: loops = %llu ms=%u",msg,lim,GetTickCount()-mss);}
//+------------------------------------------------------------------+
class A
{
private:
   double            _Ask, _Bid;
   double            f1()  { return(_Ask + 1.0/(1.0+(double)rand())); }
   double            f2()  { return(_Bid + 1.0/(1.0+(double)rand())); }
   double            f3()  { return(_Ask/_Bid + 1.0/(1.0+(double)rand())); }
public:
   double            calc(const MqlTick &tick){ _Ask = tick.ask; _Bid = tick.bid; return(f1() + f2() + f3()); }
};
//+------------------------------------------------------------------+
class B
{
private:
   double            f1(const MqlTick &t)  { return(t.ask + 1.0/(1.0+(double)rand())); }
   double            f2(const MqlTick &t)  { return(t.bid + 1.0/(1.0+(double)rand())); }
   double            f3(const MqlTick &t)  { return(t.ask/t.bid + 1.0/(1.0+(double)rand())); }
public:
   double            calc(const MqlTick &tick){ return(f1(tick) + f2(tick) + f3(tick)); }
};
//+------------------------------------------------------------------+
void OnStart()
{
   A a;
   B b;
   MqlTick rnd_tick;
   for(int i=0; i<5; i++)
   {
      SpeedTest(TST_COUNT, "class A : ",
               rnd_tick.ask = 1.0 + 1.0 / (1.0 + (double)rand());
               rnd_tick.bid = 1.0 + 1.0 / (1.0 + (double)rand());
               double res = a.calc(rnd_tick);
      );
   
      SpeedTest(TST_COUNT, "class B : ",
               rnd_tick.ask = 1.0 + 1.0 / (1.0 + (double)rand());
               rnd_tick.bid = 1.0 + 1.0 / (1.0 + (double)rand());
               double res = b.calc(rnd_tick);
      );
   }
}
//+------------------------------------------------------------------+

2020.07.25 18:00:07.293 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46141

2020.07.25 18:00:45.273 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=37968

2020.07.25 18:01:31.405 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46141

2020.07.25 18:02:09.423 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38016

2020.07.25 18:02:55.558 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46125

2020.07.25 18:03:33.635 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38078

2020.07.25 18:04:21.969 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=48344

2020.07.25 18:05:00.113 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38140

2020.07.25 18:05:46.503 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46391

2020.07.25 18:06:24.573 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38062

La velocidad es fundamental para la optimización, por eso quería saberlo.

en general, la referencia debe pasar el precio actual a todos los métodos



UPD:

//+------------------------------------------------------------------+
class C
{
private:
   double            f1(const double &a, const double &b)  { return(a + 1.0/(1.0+(double)rand())); }
   double            f2(const double &a, const double &b)  { return(b + 1.0/(1.0+(double)rand())); }
   double            f3(const double &a, const double &b)  { return(a/b + 1.0/(1.0+(double)rand())); }
public:
   double            calc(const MqlTick &tick){const double ask = tick.ask; const double bid = tick.bid; return(f1(ask,bid) + f2(ask,bid) + f3(ask,bid)); }
};
//+------------------------------------------------------------------+

2020.07.25 19:03:37.210 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46141

2020.07.25 19:04:15.201 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38000

2020.07.25 19:04:53.188 class_global (EURUSD,H1) class C : : bucles = 10000000000 ms=37984

2020.07.25 19:05:39.321 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46125

2020.07.25 19:06:17.313 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38000

2020.07.25 19:06:55.306 class_global (EURUSD,H1) class C : : bucles = 10000000000 ms=37985

 
Igor Makanu:

el rendimiento de mt5 es suficiente para 10500 órdenes por segundo, el canal habría sido suficiente

La verdad es que tenía que comprobarlo... si quieres hacer algo, hazlo tú mismo! )))

2020.07.25 18:00:07.293 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46141

2020.07.25 18:00:45.273 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=37968

2020.07.25 18:01:31.405 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46141

2020.07.25 18:02:09.423 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38016

2020.07.25 18:02:55.558 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46125

2020.07.25 18:03:33.635 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38078

2020.07.25 18:04:21.969 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=48344

2020.07.25 18:05:00.113 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38140

2020.07.25 18:05:46.503 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46391

2020.07.25 18:06:24.573 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38062

La velocidad es fundamental para la optimización, por eso quería saberlo.

en general, la referencia debe pasar el precio actual a todos los métodos



UPD:

2020.07.25 19:03:37.210 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46141

2020.07.25 19:04:15.201 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38000

2020.07.25 19:04:53.188 class_global (EURUSD,H1) class C : : bucles = 10000000000 ms=37984

2020.07.25 19:05:39.321 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46125

2020.07.25 19:06:17.313 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38000

2020.07.25 19:06:55.306 class_global (EURUSD,H1) class C : : bucles = 10000000000 ms=37985

Para empezar haz las mismas condiciones de trabajo)))) Porque has insertado un operador de asignación absolutamente innecesario (2 pcs), creando así un código no óptimo a sabiendas))

//+------------------------------------------------------------------+
class A
{
private:
   double            _Ask, _Bid;
   double            f1()  { return(_Ask + 1.0/(1.0+(double)rand())); }
   double            f2()  { return(_Bid + 1.0/(1.0+(double)rand())); }
   double            f3()  { return(_Ask/_Bid + 1.0/(1.0+(double)rand())); }
public:
   void              Init() {_Ask = 1.0 + 1.0 / (1.0 + (double)rand());
                             _Bid = 1.0 + 1.0 / (1.0 + (double)rand());}
   double            calc(){return(f1() + f2() + f3()); }
};
//+------------------------------------------------------------------+
class B
{
private:
   double            f1(const MqlTick &t)  { return(t.ask + 1.0/(1.0+(double)rand())); }
   double            f2(const MqlTick &t)  { return(t.bid + 1.0/(1.0+(double)rand())); }
   double            f3(const MqlTick &t)  { return(t.ask/t.bid + 1.0/(1.0+(double)rand())); }
public:
   double            calc(const MqlTick &tick){ return(f1(tick) + f2(tick) + f3(tick)); }
};
//+------------------------------------------------------------------+
void OnStart()
{
   A a;
   B b;
   MqlTick rnd_tick;
   for(int i=0; i<5; i++)
   {
      SpeedTest(TST_COUNT, "class A : ",
               a.Init();
               double res = a.calc();
      );
   
      SpeedTest(TST_COUNT, "class B : ",
               rnd_tick.ask = 1.0 + 1.0 / (1.0 + (double)rand());
               rnd_tick.bid = 1.0 + 1.0 / (1.0 + (double)rand());
               double res = b.calc(rnd_tick);
      );
   }
}

Y ahora una pregunta: ¿qué le conviene más? Por supuesto, puedes arrastrar una cadena de enlaces a través de los parámetros del método, o puedes hacerlo de forma agradable. Compara tú mismo las velocidades)))

 
Vladimir Simakov:

Pero tomaste un operador de asignación absolutamente innecesario (2 pcs.), y así creaste un código subóptimo a sabiendas))

¡No fui yo!

Es el Centro de Conocimiento de IBM !https://www.ibm.com/support/knowledgecenter/ru/ssw_aix_72/performance/coding_style_best_perf.html



Las condiciones son las mismas allí, cada vez que hay que llamar al gestor de la clase (o superclase, no lo sé)

y llama al resto de clases que trabajan según sus estrategias

pero por el bien de la discusión, la variante C realmente gana en velocidad, por lo que es el centro de knoelege que tipo de dice la verdad

 
Pavel Verveyko:

Me pregunto si esto es un fallo o una característica)

Hay una estructura dentro de la instancia de la clase.

Pongo un punto para ver el contenido de la estructura.
Pero sólo se muestra si pongo corchetes.
Aunque la estructura está en una sola instancia.

el problema se resuelve si la clase no es un elemento de la matriz.




aquí está el código para "husmear".

intentar compilarlo, incluso con errores. A veces "despierta" al editor

 
Igor Makanu:

¡ese no soy yo!

es el Centro de Conocimiento de IBM !el precio actual a todos los métodos



UPD:

2020.07.25 19:03:37.210 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46141

2020.07.25 19:04:15.201 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38000

2020.07.25 19:04:53.188 class_global (EURUSD,H1) class C : : bucles = 10000000000 ms=37984

2020.07.25 19:05:39.321 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46125

2020.07.25 19:06:17.313 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38000

2020.07.25 19:06:55.306 class_global (EURUSD,H1) class C : : bucles = 10000000000 ms=37985

Igor Makanu:

¡este no soy yo!

este es el Centro de Conocimiento de IBM !https://www.ibm.com/support/knowledgecenter/ru/ssw_aix_72/performance/coding_style_best_perf.html



Las condiciones son las mismas allí, cada tick hay que llamar al gestor de la clase (o superclase, no sé)

y llama al resto de clases que trabajan según sus estrategias

pero para el punto - la opción C realmente gana en velocidad, es decir, es knoelege_center kinda dice la verdad

Por supuesto que gana). Pero no porque esté escrito de forma óptima, sino porque los compiladores se han vuelto más inteligentes). Pura optimización. No hay asignación de valores de compra y venta en el código de liberación)) Pero cuando tengas un poco menos de parámetros que procesar, y la lógica de negocio del proyecto sea un poco más que abrir un pedido por indicador, entonces veré cómo te cansas de arrastrar cadenas de enlaces por todo el proyecto)))) Y sí, ya te hablé del pecado de la optimización excesiva. Créeme, no lo necesitas en el 98% de los casos.

 
Vladimir Simakov:

Y sí, ya te he hablado del pecado de la sobreoptimización. Créeme, no lo necesitas el 98% de las veces.

¡Yo sí!... pero mi instinto me dice que no lo conseguiré hasta que lo haga bien ))))

Bien, gracias, hay algo de sentido común en esta investigación.

 
Igor Makanu:


UPD:

2020.07.25 19:03:37.210 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46141

2020.07.25 19:04:15.201 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38000

2020.07.25 19:04:53.188 class_global (EURUSD,H1) class C : : bucles = 10000000000 ms=37984

2020.07.25 19:05:39.321 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46125

2020.07.25 19:06:17.313 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38000

2020.07.25 19:06:55.306 class_global (EURUSD,H1) class C : : bucles = 10000000000 ms=37985

Prueba también de esta manera:

class D
{
   double f1(const double &a, const double &b)  { return(a + 1.0/(1.0+(double)rand())); }
   double f2(const double &a, const double &b)  { return(b + 1.0/(1.0+(double)rand())); }
   double f3(const double &a, const double &b)  { return(a/b + 1.0/(1.0+(double)rand())); }
   
public:
   double calc( const MqlTick& tick )
   {
      return f1( tick.ask, tick.bid ) + f2( tick.ask, tick.bid ) + f3( tick.ask, tick.bid );
   }
};
 
Koldun Zloy:

Prueba también de esta manera:

2020.07.26 09:39:21.350 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46157

2020.07.26 09:39:59.402 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38046

2020.07.26 09:40:37.455 class_global (EURUSD,H1) class C : : bucles = 10000000000 ms=38063

2020.07.26 09:41:15.485 class_global (EURUSD,H1) class D : : : loops = 10000000000 ms=38031

2020.07.26 09:42:01.749 class_global (EURUSD,H1) class A : : loops = 10000000000 ms=46266

2020.07.26 09:42:39.754 class_global (EURUSD,H1) class B : : loops = 10000000000 ms=38000

2020.07.26 09:43:17.753 class_global (EURUSD,H1) class C : : bucles = 10000000000 ms=38000

2020.07.26 09:43:55.743 class_global (EURUSD,H1) class D : : loops = 10000000000 ms=37984

Los mismos valores, la velocidad de la prueba es "flotante" por alguna razón, pero pasar parámetros en los métodos por el enlace sigue siendo más eficiente