Perguntas sobre OOP em MQL5 - página 87

 
Vladimir Simakov:
Pergunta. Por que você precisa de um acordeão? Se em um método, em uma classe, em cavalo esférico, sim, em vácuo físico (bem, estou sem fôlego)))), então sim, faz sentido. E se num projeto real, seja uma classe a nível global, ou um solitário que lide com todo esse tricomudin (desculpe pelo bourbon))))) extra no início do manipulador, e, peça diretamente a partir dele em qualquer lugar)))

é um gerente de classe que distribui tarefas e obtém resultados de um pequeno rebanho de classes subordinadas ))))

em geral, é difícil explicar de uma forma sóbria

mas a questão é relevante - como o endereçamento dos campos comuns é feito ao ler os valores desses campos a partir de diferentes métodos e com muita freqüência

 
Igor Makanu:

é um gerente de classe que distribui tarefas e obtém resultados de um pequeno rebanho de classes subordinadas ))))

em geral, é difícil explicar de uma forma sóbria

mas a questão é relevante - como o endereçamento dos campos comuns é feito ao ler os valores desses campos a partir de diferentes métodos e com muita freqüência

Veja. No início do manipulador, não importa qual, você começa gSomeGlobal.SomeEvent(...), ou, se solteiro, Alone::SomeEvent(...), neste método faça o manejo estatal requerido e, em seguida, simplesmente solicite os dados requeridos através de getters. Desde que você não seja um escalpador de alta freqüência, você pode parafusar todos os defensores da velocidade, embora não haja nenhuma sobrecarga especial aqui)))
 
Vladimir Simakov:
Veja também. No início do manipulador, não importa qual, você começa gSomeGlobal.SomeEvent(...), ou, se solteiro, Alone::SomeEvent(...), neste método você faz o processamento de estado requerido e, então, você apenas solicita os dados requeridos através de getters. Desde que você não seja um escalpador de alta freqüência, você pode parafusar todos os defensores da velocidade, embora não haja nenhuma sobrecarga especial aqui)))

O desempenho do mt5 é suficiente para 10500 pedidos por segundo, o canal teria sido suficiente

Eu estava procurando a verdade, eu tinha que verificá-la... se você quiser fazer alguma coisa, faça você mesmo! )))

#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

A velocidade é fundamental para a otimização, é por isso que eu queria saber sobre isso.

em geral, a referência deve passar o preço atual para todos os 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 : : loops = 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 : : loops = 10000000000 ms=37985

 
Igor Makanu:

O desempenho do mt5 é suficiente para 10500 pedidos por segundo, o canal teria sido suficiente

Eu estava procurando a verdade, eu tinha que verificá-la... se você quiser fazer alguma coisa, faça você mesmo! )))

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

A velocidade é fundamental para a otimização, é por isso que eu queria saber sobre isso.

em geral, a referência deve passar o preço atual para todos os 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 : : loops = 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 : : loops = 10000000000 ms=37985

Para começar, fazer as mesmas condições de trabalho)))) Porque você inseriu um operador de atribuição absolutamente desnecessário (2 pcs), criando assim um código intencionalmente não otimizado)))

//+------------------------------------------------------------------+
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);
      );
   }
}

E agora uma pergunta: o que é mais conveniente para você? É claro que você pode arrastar uma cadeia de elos através dos parâmetros do método, ou você pode fazer isso de forma agradável. Compare você mesmo as velocidades))))

 
Vladimir Simakov:

Mas você pegou um operador de atribuição absolutamente desnecessário (2 pcs.), e assim criou um código intencionalmente sub-ótimo)))

Esse não era eu!

É o IBM Knowledge Center !https://www.ibm.com/support/knowledgecenter/ru/ssw_aix_72/performance/coding_style_best_perf.html



As condições são as mesmas lá, cada carrapato que você precisa chamar o gerente de classe (ou super classe, eu não sei)

e chama o resto das classes que trabalham de acordo com suas estratégias

mas por uma questão de argumento, a variante C realmente ganha em velocidade, então é o knoelege_center que fala a verdade

 
Pavel Verveyko:

Será que isto é uma falha ou uma característica?

Existe uma estrutura dentro da instância de classe.

Coloco um ponto para ver o conteúdo da estrutura.
Mas ele só é exibido se eu colocar colchetes.
Embora a estrutura esteja em uma única instância.

o problema é resolvido se a classe não for um elemento de matriz.




aqui está o código para "bisbilhotar".

tentar compilá-lo, mesmo com erros. Às vezes "acorda" o editor

 
Igor Makanu:

não sou eu!

é o IBM Knowledge Center !o preço atual para todos os 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 : : loops = 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 : : loops = 10000000000 ms=37985

Igor Makanu:

este não sou eu!

este é o IBM Knowledge Center !https://www.ibm.com/support/knowledgecenter/ru/ssw_aix_72/performance/coding_style_best_perf.html



As condições são as mesmas lá, cada carrapato que você precisa chamar o gerente de classe (ou superclasse, eu não sei)

e chama o resto das classes que trabalham de acordo com suas estratégias

mas para o ponto - a opção C realmente ganha em velocidade, ou seja, é knoelege_center fala um pouco a verdade

É claro que ganha). Mas não porque está escrito de forma ótima, mas porque os compiladores se tornaram mais inteligentes). Pura otimização. Não há atribuição de valores de Ask e Bid no código de liberação)))) Mas quando você tem um pouco menos de parâmetros para processar, e a lógica comercial do projeto será um pouco mais do que abrir um pedido por indicador, então verei como você se cansa de arrastar uma seqüência de links através de todo o projeto)))) E sim, eu já lhe falei sobre o pecado da otimização excessiva. Confie em mim, você não precisa disso em 98% dos casos.

 
Vladimir Simakov:

E sim, eu já lhe falei do pecado da otimização excessiva. Confie em mim, você não precisa disso 98% do tempo.

Eu quero!... mas meu instinto me diz que não vou conseguir até que eu acerte ))))

Certo, obrigado, há algum bom senso nesta pesquisa.

 
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 : : loops = 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 : : loops = 10000000000 ms=37985

Tente também desta forma:

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:

Tente também desta forma:

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 : : loops = 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 : loops = 10000000000 ms=38000

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

Os mesmos valores, a velocidade de teste é "flutuante" por alguma razão, mas a passagem de parâmetros nos métodos pelo link é ainda mais eficiente