Domande su OOP in MQL5 - pagina 87

 
Vladimir Simakov:
Domanda. Domanda: Perché hai bisogno di una fisarmonica? Se in un metodo, una classe, nel cavallo sferico, sì, nel vuoto fisico (beh, sono ubriaco )))), allora sì, ha senso. E se in un progetto reale, o una classe a livello globale, o un solitario che gestisce tutto questo trichomudin (scusate per il bourbon))))) extra all'inizio del gestore, e, richiesta direttamente da esso in qualsiasi luogo))

è un manager di classe che distribuisce compiti e ottiene risultati da un piccolo branco di classi subordinate ))))

in generale, è difficile spiegare in modo sobrio

ma la domanda è rilevante - come viene eseguito l'indirizzamento dei campi comuni quando si leggono i valori di questi campi da diversi metodi e molto spesso

 
Igor Makanu:

è un manager di classe che distribuisce compiti e ottiene risultati da un piccolo branco di classi subordinate ))))

in generale, è difficile spiegare in modo sobrio

ma la domanda è rilevante - come viene eseguito l'indirizzamento dei campi comuni quando si leggono i valori di questi campi da diversi metodi e molto spesso

Guarda. All'inizio del gestore, non importa quale, si avvia gSomeGlobal.SomeEvent(...), o, se singolo, Alone::SomeEvent(...), in questo metodo si fa la gestione dello stato richiesto e, poi, si richiedono semplicemente i dati richiesti tramite i getter. Finché non sei uno scalper ad alta frequenza, puoi fottere tutti i sostenitori della velocità, anche se non c'è un overhead speciale qui)))
 
Vladimir Simakov:
Vedi anche. All'inizio del gestore, non importa quale, si avvia gSomeGlobal.SomeEvent(...), o, se singolo, Alone::SomeEvent(...), in questo metodo si fa l'elaborazione di stato necessaria e poi si richiedono solo i dati necessari tramite i getter. Finché non sei uno scalper ad alta frequenza, puoi fottere tutti i sostenitori della velocità, anche se non c'è un overhead speciale qui)))

Le prestazioni di mt5 sono sufficienti per 10500 ordini al secondo, il canale sarebbe stato sufficiente

Stavo cercando la verità, dovevo controllare... se vuoi fare qualcosa, fallo da solo! )))

#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) classe A : : loop = 10000000000 ms=46141

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

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

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

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

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

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

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

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

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

La velocità è fondamentale per l'ottimizzazione, ecco perché volevo saperlo.

in generale, il riferimento deve passare il prezzo corrente a tutti i metodi



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) classe A : : loop = 10000000000 ms=46141

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

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

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

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

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

 
Igor Makanu:

Le prestazioni di mt5 sono sufficienti per 10500 ordini al secondo, il canale sarebbe stato sufficiente

Stavo cercando la verità, dovevo controllare... se vuoi fare qualcosa, fallo da solo! )))

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

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

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

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

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

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

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

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

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

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

La velocità è fondamentale per l'ottimizzazione, ecco perché volevo saperlo.

in generale, il riferimento deve passare il prezzo corrente a tutti i metodi



UPD:

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

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

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

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

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

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

Per cominciare fare le stesse condizioni di lavoro)))) Perché hai inserito un operatore di assegnazione assolutamente non necessario (2 pezzi), creando così un codice consapevolmente non ottimale))

//+------------------------------------------------------------------+
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 ora una domanda: cosa è più conveniente per voi? Naturalmente, potete trascinare una catena di collegamenti attraverso i parametri del metodo, o potete farlo in modo carino. Confrontate voi stessi le velocità)))

 
Vladimir Simakov:

Ma hai preso un operatore di assegnazione assolutamente non necessario (2 pz.), e quindi hai creato un codice consapevolmente sub-ottimale))

Non ero io!

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



Le condizioni sono le stesse lì, ogni tick è necessario chiamare il gestore della classe (o superclasse, non so)

e chiama il resto delle classi che lavorano secondo le loro strategie

ma per amor di discussione, la variante C vince davvero in velocità, quindi è il knoelege_center che dice un po' la verità

 
Pavel Verveyko:

Mi chiedo se questo è un glitch o una caratteristica)

C'è una struttura all'interno dell'istanza della classe.

Ho messo un punto per vedere il contenuto della struttura.
Ma viene visualizzato solo se metto le parentesi quadre.
Anche se la struttura è in una singola istanza.

il problema è risolto se la classe non è un elemento dell'array.




Ecco il codice per "frugare".

provare a compilarlo, anche con errori. A volte "sveglia" l'editor

 
Igor Makanu:

non sono io!

è IBM Knowledge Center!il prezzo corrente a tutti i metodi



UPD:

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

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

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

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

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

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

Igor Makanu:

questo non sono io!

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



Le condizioni sono le stesse, ogni tick è necessario chiamare il gestore della classe (o superclasse, non so)

e chiama il resto delle classi che lavorano secondo le loro strategie

ma per il punto - l'opzione C vince davvero in velocità, cioè è knoelege_center dice la verità

Certo che vince). Ma non perché sia scritto in modo ottimale, ma perché i compilatori sono diventati più intelligenti). Ottimizzazione pura. Non c'è assegnazione di valori di Ask e Bid nel codice di rilascio)) Ma quando avrete un po' meno parametri da elaborare, e la logica di business del progetto sarà un po' più che aprire un ordine per indicatore, allora vedrò come vi stancherete di trascinare una stringa di link attraverso l'intero progetto)))) E sì, vi ho già parlato del peccato dell'ottimizzazione eccessiva. Credetemi, non ne avete bisogno nel 98% dei casi.

 
Vladimir Simakov:

E sì, vi ho già parlato del peccato di sovraottimizzazione. Credetemi, non ne avete bisogno il 98% delle volte.

Lo faccio!... ma il mio istinto mi dice che non posso farlo bene finché non lo faccio bene ))))

Ok, grazie, c'è del buon senso in questa ricerca.

 
Igor Makanu:


UPD:

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

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

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

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

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

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

Prova anche in questo modo:

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:

Prova anche in questo modo:

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

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

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

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

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

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

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

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

Stessi valori, la velocità del test è "fluttuante" per qualche motivo, ma passare parametri nei metodi tramite il link è ancora più efficiente