Features of the mql5 language, subtleties and tricks - page 237

 
fxsaber #:

Looked at the format.

Probably won't speed it up. Heard about the miraculous speed of the switch, though.

A sparse switch doesn't give miraculous speed.

The most marvellous speed will be in a switch with cases from zero to 255 in increments of 1

 
Slava #:

Sparse switch doesn't give you marvellous speed.

The most marvellous speed will be in a switch with cases from zero to 255 in increments of 1

Thank you.

 
Nikolai Semko # :

my results from your test:



I don't like the test itself very much, because 10 million of the same calculations take place in the test. In this case, there is no guarantee that the compiler will not give surprises in its attempts to optimise the code.
And these values should be divided by 21, because there are 21*10 000 000 iterations in total.

However, this test also confirms my conclusions, but for my processor, which seems to be fresher and, therefore, uses modern performance features to the maximum and, therefore, is more objective because it is more up-to-date.


It would be interesting to see the results of this test for others.

Thanks.

It was late yesterday when I posted the results WITHOUT compiler optimisation.

Here are the results with cpu='AVX2 + FMA3' and max optimisation.


 
Nikolai Semko #:

The main difficulty in this algorithm is calculating the start time of the month (highlighted in green).

The most interesting thing in the code and almost not touched upon in the discussion.

 
fxsaber #:

The most interesting thing in the code and almost not touched on in the discussion.

There the year starts on the 1st of March instead of the 1st of January.
This is a tip I saw on stackoverflow. It was a good advice.
I had to write a script to find the 30.68 factor
 

I faced the necessity to save very short code (< 15 lines) in the form of mqh-library.

template <typename T1, typename T2>
T1* New( const string &ClassName ) { return((typename(T2) == ClassName) ? new T2 : NULL); }

template <typename T1, typename T2>
T1* New( string ClassName, const T2 &FuncNew[] )
{  
  T1* Res = NULL;
  
#ifdef __MQL5__
  ClassName = "class " + ClassName;
#endif // #ifdef __MQL5__
  
  for (uint i = ArraySize(FuncNew); (Res == NULL) && (bool)i--;)
    Res = FuncNew[i](ClassName);  
    
  return(Res);
}

It is a forced measure because pointers to functions are possible only for functions from the global scopus.

How short libraries do you use?

 
The signature of a template function may depend on the locations of its call.

Forum on trading, automated trading systems and testing trading strategies

Errors, bugs, questions

fxsaber, 2023.11.26 23:26

template <typename T>
void Func( void ) { Print(__FUNCSIG__); }

void OnStart()
{
  Func<int>(); // void "void OnStart()"::Func<int>()
}
 

If I understand correctly, in this case the A::f() method is inlined in g().

class A
{
  void f() {}
  void g() { this.f(); }
};


And here it is not.

class A
{
  virtual void f() {}
  void g() { this.f(); }
};


Will A::f() be inlined by the compiler in the second case, provided that no descendant objects of class A are created anywhere in the code?

 
Sometimes you need to make a breakpoint at a certain place in the Visualiser. I use such a function for this purpose.
bool IsManualChangeTester()
{
  static const bool IsVisual = MQLInfoInteger(MQL_VISUAL_MODE);
  static ENUM_CHART_MODE PrevChartMode = (ENUM_CHART_MODE)ChartGetInteger(0, CHART_MODE);  
  
  bool Res = false;
  
  if (IsVisual)
  {
    const ENUM_CHART_MODE ChartMode = (ENUM_CHART_MODE)ChartGetInteger(0, CHART_MODE);
      
    if (Res = (ChartMode != PrevChartMode))
      PrevChartMode = ChartMode;
  }
    
  return(Res);
}


With this application.

if (IsManualChangeTester())
  DebugBreak();


When I need to create this condition, I just change the graph display mode in the visualiser.

And then I analyse the behaviour of the EA in ME.

 

I never imagined that I would use a machine-generated piece of code in the source code. Especially in a place that is archival for performance.


Below is the generated code.

switch (this.Flag)
{
case 0:
  return(false);
case 1:
  return(Tick.bid >= this.bid.Max);
case 2:
  return(Tick.ask <= this.ask.Min);
case 3:
  return((Tick.bid >= this.bid.Max) || (Tick.ask <= this.ask.Min));
case 4:
  return(Tick.bid <= this.bid.Min);
case 5:
  return((Tick.bid >= this.bid.Max) || (Tick.bid <= this.bid.Min));
case 6:
  return((Tick.ask <= this.ask.Min) || (Tick.bid <= this.bid.Min));
case 7:
  return((Tick.bid >= this.bid.Max) || (Tick.ask <= this.ask.Min) || (Tick.bid <= this.bid.Min));
case 8:
  return(Tick.ask >= this.ask.Max);
case 9:
  return((Tick.bid >= this.bid.Max) || (Tick.ask >= this.ask.Max));
case 10:
  return((Tick.ask <= this.ask.Min) || (Tick.ask >= this.ask.Max));
case 11:
  return((Tick.bid >= this.bid.Max) || (Tick.ask <= this.ask.Min) || (Tick.ask >= this.ask.Max));
case 12:
  return((Tick.bid <= this.bid.Min) || (Tick.ask >= this.ask.Max));
case 13:
  return((Tick.bid >= this.bid.Max) || (Tick.bid <= this.bid.Min) || (Tick.ask >= this.ask.Max));
case 14:
  return((Tick.ask <= this.ask.Min) || (Tick.bid <= this.bid.Min) || (Tick.ask >= this.ask.Max));
case 15:
  return((Tick.bid >= this.bid.Max) || (Tick.ask <= this.ask.Min) || (Tick.bid <= this.bid.Min) || (Tick.ask >= this.ask.Max));
}

A much more concise script was written for the generation. It can be expedient to quickly test hypotheses and avoid human errors.