Особенности языка mql5, тонкости и приёмы работы - страница 260

 
Комментарии, не относящиеся к этой теме, были перенесены в "Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам".
 
amrali #:

Более быстрая функция TimeToStruct() для декодирования переменных времени суток, чтобы получить все компоненты даты и времени.

Некоторые части кода могут быть использованы повторно для извлечения интересующих компонентов по отдельности.

Бенчмарк:

Результаты:

думал что предложенный Вами вариант самый быстрый, но оказалось, что можно сделать еще быстрее:

bool TimeToStruct2100(datetime time, MqlDateTime& dt_struct) {
   static const int dm[13] = {0, 0, 31, 59, 90, 120, 151, 181, 212,243, 273, 304, 334};
   static int last_days = 0;
   static int last_result_m = 0;
   static int last_result_y = 0;
   static int last_result_yd = 0;
   static int last_result_d = 0;
   int days    = (int)(time / (60 * 60 * 24));
   if (last_days!=days) {
      last_days = days;
      last_result_y    = ((days << 2) + 2) / 1461;
      last_result_yd = days - ((last_result_y * 1461 + 1) >> 2);
      int isleap  = ((last_result_y & 3) == 2);
      int leapadj = ((last_result_yd < (59 + isleap)) ? 0 : (2 - isleap));
      last_result_m   = ((((last_result_yd + leapadj) * 12) + 373) / 367);
      last_result_d   = last_result_yd-dm[last_result_m]+1 -((last_result_yd>59)?isleap:0);
   }

   int HH  = (int)((time / 3600) % 24)                   ;
   int MM  = (int)((time / 60) % 60)                     ;
   int SS  = (int)(time % 60)                            ;
   int dow = (days + 4) % 7                                 ;

   dt_struct.year           = last_result_y+1970;
   dt_struct.mon            = last_result_m;
   dt_struct.day            = last_result_d;
   dt_struct.hour           = HH;
   dt_struct.min            = MM;
   dt_struct.sec            = SS;
   dt_struct.day_of_week    = dow;
   dt_struct.day_of_year    = last_result_yd;
   return (true);
}

Я собрал в кучу разные методы, которые здесь уже фигурировали.
Дополнительным преимуществом является то, что функция запоминает в статических переменных основные вычисления и применяет их, если день совпадает с днем из предыдущего обращения к функции. В реальности таких вызовов будет более 90%. Поэтому выйгрыш будет еще больше, чем в этом рандомном тесте. Но тест показывает, что данная функция примерно в три раза быстрее работает штатной.

2024.05.01 23:42:20.421 TestDate3 (EURUSD,M1)   1 - 23.23 ns, контрольная сумма = 231120216492  // TimeToStruct
2024.05.01 23:42:21.639 TestDate3 (EURUSD,M1)   2 - 12.18 ns, контрольная сумма = 231120216492  // amrali
2024.05.01 23:42:22.361 TestDate3 (EURUSD,M1)   2 - 7.22 ns, контрольная сумма = 231120216492  // TimeToStruct2100
2024.05.01 23:42:31.374 TestDate3 (EURUSD,M1)   1 - 23.41 ns, контрольная сумма = 231122296278  // TimeToStruct
2024.05.01 23:42:32.603 TestDate3 (EURUSD,M1)   2 - 12.29 ns, контрольная сумма = 231122296278  // amrali
2024.05.01 23:42:33.350 TestDate3 (EURUSD,M1)   2 - 7.48 ns, контрольная сумма = 231122296278  // TimeToStruct2100
2024.05.01 23:42:39.681 TestDate3 (EURUSD,M1)   1 - 23.25 ns, контрольная сумма = 231122653514  // TimeToStruct
2024.05.01 23:42:40.895 TestDate3 (EURUSD,M1)   2 - 12.15 ns, контрольная сумма = 231122653514  // amrali
2024.05.01 23:42:41.629 TestDate3 (EURUSD,M1)   2 - 7.34 ns, контрольная сумма = 231122653514  // TimeToStruct2100
Необходимо дополнительно напомнить, что корректно работает до 28 февраля 2100 года, т.к. не учитывается Григорианский календарь, в котором 2100 год не будет високосным.
Файлы:
TestDate3.mq5  12 kb
 
Nikolai Semko #:

Я собрал в кучу разные методы, которые здесь уже фигурировали.

Добавил этот. x64.

1 - 39.83 ns, контрольная сумма = 23111710226  // TimeToStruct
2 - 24.80 ns, контрольная сумма = 23111710226  // amrali
3 - 16.08 ns, контрольная сумма = 23111710226  // TimeToStruct2100
4 - 12.30 ns, контрольная сумма = 23111710226  // TimeToStruct2100_fxsaber

Необходимо дополнительно напомнить, что корректно работает до 28 февраля 2100 года, т.к. не учитывается Григорианский календарь, в котором 2100 год не будет високосным.

Можно снять это ограничение добавкой эпох.

 
fxsaber #:

Можно снять это ограничение добавкой эпох.

Смысла нет. Вероятность жизни MQL в 2100 равна нулю 
 
fxsaber #:

Добавил этот. x64.

у меня на более новом камне другая картина

2024.05.02 01:26:08.576 TestDate3 (EURUSD,M1)   1 - 28.50 ns, контрольная сумма = 231124680107  // TimeToStruct
2024.05.02 01:26:09.897 TestDate3 (EURUSD,M1)   2 - 13.21 ns, контрольная сумма = 231124680107  // amrali
2024.05.02 01:26:10.721 TestDate3 (EURUSD,M1)   2 - 8.25 ns, контрольная сумма = 231124680107  // TimeToStruct2100
2024.05.02 01:26:11.549 TestDate3 (EURUSD,M1)   2 - 8.28 ns, контрольная сумма = 231124680107  // TimeToStruct2100 fxsaber
2024.05.02 01:26:18.906 TestDate3 (EURUSD,M1)   1 - 28.03 ns, контрольная сумма = 231123677979  // TimeToStruct
2024.05.02 01:26:20.204 TestDate3 (EURUSD,M1)   2 - 12.98 ns, контрольная сумма = 231123677979  // amrali
2024.05.02 01:26:20.992 TestDate3 (EURUSD,M1)   2 - 7.88 ns, контрольная сумма = 231123677979  // TimeToStruct2100
2024.05.02 01:26:21.799 TestDate3 (EURUSD,M1)   2 - 8.07 ns, контрольная сумма = 231123677979  // TimeToStruct2100 fxsaber
2024.05.02 01:26:27.976 TestDate3 (EURUSD,M1)   1 - 32.04 ns, контрольная сумма = 231120182713  // TimeToStruct
2024.05.02 01:26:29.306 TestDate3 (EURUSD,M1)   2 - 13.30 ns, контрольная сумма = 231120182713  // amrali
2024.05.02 01:26:30.081 TestDate3 (EURUSD,M1)   2 - 7.74 ns, контрольная сумма = 231120182713  // TimeToStruct2100
2024.05.02 01:26:30.914 TestDate3 (EURUSD,M1)   2 - 8.33 ns, контрольная сумма = 231120182713  // TimeToStruct2100 fxsaber

в добавок у меня реализовано через статические переменные, что по идее должно замедлять тест рандомного времени и сильно ускорять на упорядоченном входном потоке времени.


Файлы:
TestDate3.mq5  16 kb
 
Nikolai Semko #:

у меня на более новом камне другая картина

Тогда вопрос к разработчикам, почему для оптимального выполнения нужно создавать камне-зависимый код?

 
fxsaber #:

Тогда вопрос к разработчикам, почему для оптимального выполнения нужно создавать камне-зависимый код?

читаем эту статью
https://habr.com/ru/amp/publications/811151/

Кто реально угрожает C++ (нет, Rust, не ты) / Habr
  • habr.com
Привет! Меня зовут Александр Каленюк, и я крепко подсел на C++. Пишу на C++ 18 лет кряду, и все эти годы отчаянно пытаюсь избавиться от этой разрушительной зависимости. Всё началось в конце 2005 года, когда мне довелось писать движок для симуляции 3D-пространства. В этом движке было буквально всё, чем язык C++ мог похвастаться в 2005 году...
 
Nikolai Semko #:

читаем эту статью
https://habr.com/ru/amp/publications/811151/

Спасибо. Но все же в статье демонстрируются разницы в производительности для совсем разных железяк.

Здесь же отличаются Intel-камни.

 
fxsaber #:

Спасибо. Но все же в статье демонстрируются разницы в производительности для совсем разных железяк.

Здесь же отличаются Intel-камни.

Intel-камни, разнесенных во времени - это могут быть совсем разные железяки. Один и тот же код может выполняться совсем по разной логике внутри процессора. Система команд любого производителя тоже имеет свою эволюцию 
 
Nikolai Semko #:

Я собрал в кучу разные методы, которые здесь уже фигурировали.

Для сравнения скоростей предложенных методов (штатный неинтересен) имеет смысл делать только такую контрольную сумму.
uint mm =dt.year+ dt.mon+ dt.day/*+ dt.hour+ dt.min+ dt.sec+ dt.day_of_week+ dt.day_of_year*/;
DayOfYear - не представляю, для чего нужно. Внутрисуточное время (и день недели) - элементарно всегда. А вот первые три слагаемые - основная сложность, поэтому их реализации и стоит сравнивать. Как и обратный функционал.
Причина обращения: