Fragen zu OOP in MQL5 - Seite 87

 
Vladimir Simakov:
Frage. Warum brauchen Sie ein Akkordeon? Wenn in einer Methode, einer Klasse, im sphärischen Pferd, ja, im physikalischen Vakuum (na ja, ich bin aus dem Atem)))), dann ja, es macht Sinn. Und wenn in einem realen Projekt, entweder eine Klasse auf globaler Ebene, oder ein Einzelgänger, die alle diese trichomudin (sorry für die zusätzliche bourbon))))) am Anfang des Handlers, und, Anfrage direkt von ihm an jedem Ort))) behandelt

es ist ein Klassenmanager, der Aufgaben verteilt und Ergebnisse von einer kleinen Herde von untergeordneten Klassen erhält ))))

im Allgemeinen ist es schwierig, nüchtern zu erklären

aber die Frage ist relevant - wie wird die Adressierung der gemeinsamen Felder durchgeführt, wenn die Werte dieser Felder aus verschiedenen Methoden und sehr oft gelesen werden

 
Igor Makanu:

es ist ein Klassenmanager, der Aufgaben verteilt und Ergebnisse von einer kleinen Herde von untergeordneten Klassen erhält ))))

im Allgemeinen ist es schwierig, nüchtern zu erklären

aber die Frage ist relevant - wie wird die Adressierung der gemeinsamen Felder durchgeführt, wenn die Werte dieser Felder aus verschiedenen Methoden und sehr oft gelesen werden

Sehen Sie. Am Anfang des Handlers, egal welcher, starten Sie gSomeGlobal.SomeEvent(...), oder, falls einzeln, Alone::SomeEvent(...), führen in dieser Methode die notwendige Zustandsbehandlung durch und fragen dann einfach die benötigten Daten über Getter ab. Solange Sie kein Hochfrequenz-Scalper sind, können Sie alle Geschwindigkeitsbefürworter verarschen, obwohl es hier keinen besonderen Overhead gibt)))
 
Vladimir Simakov:
Siehe auch. Am Anfang des Handlers, egal welcher, starten Sie gSomeGlobal.SomeEvent(...), oder, falls einzeln, Alone::SomeEvent(...), in dieser Methode führen Sie die notwendige Zustandsverarbeitung durch und fragen dann nur noch die benötigten Daten über Getter ab. Solange Sie kein Hochfrequenz-Scalper sind, können Sie alle Geschwindigkeitsbefürworter verarschen, obwohl es hier keinen besonderen Overhead gibt)))

mt5 Leistung ist genug für 10500 Aufträge pro Sekunde, der Kanal wäre genug gewesen

Ich war auf der Suche nach der Wahrheit, ich musste es überprüfen... wenn du etwas tun willst, dann tu es selbst! )))

#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

Die Geschwindigkeit ist entscheidend für die Optimierung, deshalb wollte ich das wissen.

im Allgemeinen muss die Referenz den aktuellen Preis an alle Methoden weitergeben



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

 
Igor Makanu:

mt5 Leistung ist genug für 10500 Aufträge pro Sekunde, der Kanal wäre genug gewesen

Ich war auf der Suche nach der Wahrheit, ich musste es überprüfen... wenn du etwas tun willst, tu es selbst! )))

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

Die Geschwindigkeit ist entscheidend für die Optimierung, deshalb wollte ich das wissen.

im Allgemeinen muss die Referenz den aktuellen Preis an alle Methoden weitergeben



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

Für den Anfang machen die gleichen Arbeitsbedingungen)))) Denn Sie haben einen absolut unnötigen Zuweisungsoperator (2 Stück) eingefügt und damit einen bewusst nicht optimalen Code geschaffen)))

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

Und nun eine Frage: Was ist für Sie bequemer? Natürlich können Sie eine Kette von Verknüpfungen durch Methodenparameter ziehen, oder Sie können es einfach machen. Vergleichen Sie die Geschwindigkeiten selbst)))

 
Vladimir Simakov:

Aber Sie haben einen absolut unnötigen Zuweisungsoperator (2 Stck.) genommen und damit einen bewusst suboptimalen Code erstellt)))

Das war ich nicht!

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



Die Bedingungen sind dort die gleichen, bei jedem Tick müssen Sie den Klassenmanager (oder die Superklasse, ich weiß es nicht) aufrufen

und ruft die übrigen Klassen auf, die nach ihren Strategien arbeiten

aber um der Argumentation willen, Variante C gewinnt wirklich in der Geschwindigkeit, so ist es die knoelege_center, die irgendwie die Wahrheit spricht

 
Pavel Verveyko:

Ich frage mich, ob dies eine Störung oder ein Feature ist)

Es gibt eine Struktur innerhalb der Klasseninstanz.

Ich habe einen Punkt gesetzt, um den Inhalt der Struktur zu sehen.
Sie wird aber nur angezeigt, wenn ich eckige Klammern setze.
Obwohl sich die Struktur in einer einzigen Instanz befindet.

ist das Problem gelöst, wenn es sich bei der Klasse nicht um ein Array-Element handelt.




Hier ist der Code für das "Herumstochern".

versuchen, es zu kompilieren, auch wenn Fehler auftreten. Manchmal wird der Editor dadurch "aufgeweckt".

 
Igor Makanu:

Das bin nicht ich!

Es ist das IBM Knowledge Center!den aktuellen Preis an alle Methoden weitergeben



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

Igor Makanu:

Das bin nicht ich!

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



Die Bedingungen sind dort die gleichen, bei jedem Tick müssen Sie den Klassenmanager (oder die Superklasse, ich weiß es nicht) aufrufen

und ruft die übrigen Klassen auf, die nach ihren Strategien arbeiten

aber für den Punkt - Option C gewinnt wirklich in der Geschwindigkeit, d.h. es ist knoelege_center irgendwie spricht die Wahrheit

Natürlich gewinnt es.) Aber nicht, weil es optimal geschrieben ist, sondern weil die Compiler intelligenter geworden sind). Reine Optimierung. Es gibt keine Zuordnung von Ask- und Bid-Werten im Freigabecode))) Aber wenn Sie etwas weniger Parameter zu verarbeiten haben und die Geschäftslogik des Projekts etwas mehr ist als das Öffnen einer Bestellung per Indikator, dann kann ich verstehen, dass Sie es leid sind, eine Reihe von Links durch das gesamte Projekt zu ziehen)))) Und ja, ich habe Ihnen bereits von der Sünde der übermäßigen Optimierung erzählt. Glauben Sie mir, in 98 % der Fälle brauchen Sie das nicht.

 
Vladimir Simakov:

Und ja, ich habe Ihnen bereits von der Sünde der Überoptimierung erzählt. Glauben Sie mir, in 98 % der Fälle brauchen Sie es nicht.

Ich schon!... aber mein Bauchgefühl sagt mir, dass ich es nicht schaffe, bis ich es richtig hinbekomme ))))

Okay, danke, diese Forschung ist sehr sinnvoll.

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

Versuchen Sie auch diesen Weg:

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:

Versuchen Sie auch diesen Weg:

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

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

Gleiche Werte, Testgeschwindigkeit ist "fließend" aus irgendeinem Grund, aber die Übergabe von Parametern in Methoden durch den Link ist immer noch effizienter