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

 
Compiler Version: 4709 X64 Regular, optimization - true
Intel Core i7-2700 K  @ 3.50 GHz, AVX
With hours (dt.hour+ dt.min+ dt.sec - on), random datetimes[].
1970.01.01 00:01:44 - 2097.11.29 23:59:39
 9.40 ns, checksum = 1267172791534620   // TimeToStructMQLplus
10.00 ns, checksum = 1267172791534620   // TimeToStructFast
41.38 ns, checksum = 1267172791534620  /// MQL's TimeToStruct()


And now we add Fast-variant at the beginning.

   BENCH( Tests::TimeToStructFast           (t[i], dt), "  // TimeToStructFast");
   BENCH( Tests::TimeToStructMQLplus        (t[i], dt), "  // TimeToStructMQLplus");
   BENCH( Tests::TimeToStructFast           (t[i], dt), "  // TimeToStructFast");


And it became 30% slower.

Compiler Version: 4709 X64 Regular, optimization - true
Intel Core i7-2700 K  @ 3.50 GHz, AVX
With hours (dt.hour+ dt.min+ dt.sec - on), random datetimes[].
1970.01.01 00:00:02 - 2097.11.29 23:59:39
13.68 ns, checksum = 1238909201370816   // TimeToStructFast
 9.42 ns, checksum = 1238909201370816   // TimeToStructMQLplus
13.13 ns, checksum = 1238909201370816   // TimeToStructFast
40.30 ns, checksum = 1238909201370816  /// MQL's TimeToStruct()


In general, I do not understand how to interpret the test results.

 
fxsaber #:


And now we add Fast-variant at the beginning.


And it became 30% slower.


In general, I do not understand how to interpret the test results.

Finally others can replicate this rather curious behavior.
 
Dominik Egert #:
Maybe someone can replicate this rather curious behaviour?

This is a problem with the new compiler. Everything is fine in b4410.

 
fxsaber #:

This is a problem with the new compiler. Everything is fine in b4410.

To what I was able to find out, the issue is not stationary... Sometimes it doesn't affect the performance, and sometimes it does. But that can change, depending on where in the source code you make changes.

I experienced this effect first (I think) on 3003...
 
fxsaber #:

This function indicates the presence/absence of a particular compiler optimisation, not the presence/absence of the compiler GUI flag of the same name.

After some research, I think it could be possible to use the Ackerman function to determine if the code has been optimized by the compiler or not...

It has been used for that in the past. Maybe that could be transferred to mql.
 
Artyom Trishkin #:
Please with a link to this thread.

TimeUtils version 1.10 has been published on the codebase.

https://www.mql5.com/en/code/53970

High-Performance Time Functions (TimeUtils)
High-Performance Time Functions (TimeUtils)
  • www.mql5.com
High-performmance functions for dealing with time.
 

Cosider this old-style code to lookup up a value into a static array:

int DaysInMonth(const int year, const int month)
  {
   const int dim[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
   return ((month == 2 && IsLeapYear(year)) ? 29 : dim[month % 13]);
  }

Now static arrays are evaluated at runtime, so we can redefine the array as:

int DaysInMonth(const int year, const int month)
  {
   const int dim[13] = {0, 31, (IsLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
   return dim[month % 13];
  }
and it will compile without errors.
 

Forum on trading, automated trading systems and testing trading strategies

Peculiarities of mql5 language, subtleties and techniques of work

Dominik Egert, 2024.11.28 15:37

A little more optimised version:

bool TimeToStructMQLplus(datetime timestamp, MqlDateTime& dt_struct)
{
    static const int Months[] = { 0, 11512692, 11512196, 11511744, 11511248, 11510766, 11510272, 11509790, 11509296, 11508797, 11508318, 11507822, 11507342 };

    const uint t            = (uint)timestamp;
    const int  n            = (int)(t / 86400);
    const int  tn           = (n << 2) | 2;

    dt_struct.day_of_year   = (tn % 1461) >> 2;
    dt_struct.year          = (tn / 1461) + 1970;
    const int  isleap       = !(dt_struct.year & 3);

//    dt_struct.mon           = ((((dt_struct.day_of_year + ((dt_struct.day_of_year < (isleap + 59)) ? 0 : (2 - isleap))) * 12) + 373) / 367);
    dt_struct.mon           = ((((dt_struct.day_of_year + ((dt_struct.day_of_year < (isleap + 59)) ? 0 : (2 - isleap))) * 67) + 2075) >> 11);
    dt_struct.day           = n - (int)((dt_struct.year * 5844 - Months[dt_struct.mon]) >> 4);
    #ifndef  WITHOUT_HOURS
        dt_struct.hour      = (int)(t / 3600) % 24;
        dt_struct.min       = (int)(t / 60) % 60;
        dt_struct.sec       = (int)(t % 60);

    #endif //#ifndef WITHOUT_HOURS
    dt_struct.day_of_week   = (n + 4) % 7;

   return (true);
}

It's likely to be faster that way.

 

And inverse ?

I mean that TimeToStruct is usually paired with the inverse StructToTime function.

to find "first Monday of the previous month" , "the beginning of the current quarter" etc.

And just to decompose the current date into day-month-year (to know) it may be necessary once a day and this moment is not critical. Nobody calls TimeToStruct on every tick :-)