Быстрый TimeHour/TimeMinute?

 

Попытался ускорить TimeHour/TimeMinute, ни фига не получилось:

void OnStart()
{
        ulong s1 = GetMicrosecondCount();
        for ( datetime t = D'1990.01.01'; t <= D'2030.01.01'; t += 37 )
        {
                if ( TimeHour(t) +  TimeMinute(t) == 987654 ) break;
        }
        ulong s2 = GetMicrosecondCount();
        for ( datetime t = D'1990.01.01'; t <= D'2030.01.01'; t += 37 )
        {
                if ( TimeHourMy(t) +  TimeMinuteMy(t) == 987654 ) break;
        }
        ulong s3 = GetMicrosecondCount();
        Print( "TimeToStruct: ", (s2-s1)/1000.0, " ms, Math: ", (s3-s2)/1000.0, " ms" );
}

int TimeHour(datetime time)
{
        MqlDateTime tm;
        TimeToStruct(time,tm);
        return(tm.hour);
}
int TimeMinute(datetime time)
{
        MqlDateTime tm;
        TimeToStruct(time,tm);
        return(tm.min);
}

int TimeHourMy(datetime time)
{
        return( (time % (24 * 3600))/3600 );
}
int TimeMinuteMy(datetime time)
{
        return( ((time % (24 * 3600))%3600)/60 );
}


Оба варианта работают примерно одинаково под профилировщиком:

TimeToStruct: 4459.786 ms, Math: 4613.987 ms
TimeToStruct: 4421.249 ms, Math: 4509.065 ms

И в тестере (второй чуть быстрее, но незначительно).


Под дебагом TimeToStruct-вариант ускоряется почти в 10 раз, тогда как "математический" — всего в 2.5:

TimeToStruct: 515.626 ms, Math: 1877.093 ms
TimeToStruct: 505.737 ms, Math: 1872.513 ms


При компиляции в релиз (F7), "математический" вариант оптимизируется компилятором в 0, и как он реально работает — не понятно (есть идеи как проверить?):

TimeToStruct: 363.10 ms, Math: 0.0 ms
TimeToStruct: 360.36 ms, Math: 0.0 ms


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

Кто поможет?

 

Тут как то быстро отрабатывают ...My функции, вообще не затрачивая времени ))

ulong s2 = GetMicrosecondCount();

int tH = TimeHourMy(631142400);
int tM = TimeMinuteMy(631142400);    

ulong s3 = GetMicrosecondCount();

Print((string)tH, " Hour");
Print((string)tM, " Minutes");
Print( "Clock: ", (string)s2, " mics, ", (string)s3, " mics" );
2019.11.15 10:08:23.482 TestScript (EURUSD,M1)  21 Hour
2019.11.15 10:08:23.482 TestScript (EURUSD,M1)  20 Minutes
2019.11.15 10:08:23.482 TestScript (EURUSD,M1)  Clock: 176 mics, 176 mics
 

И в цикле тоже показывает чудеса ))

   int tH = 0;
   int tM = 0;
   
   ulong s2 = GetMicrosecondCount();
   
   for ( datetime t = 631142400123456; t <= 1893446400123456; t++ )
   {
      tH = TimeHourMy(t);
      tM = TimeMinuteMy(t);    
   }

   ulong s3 = GetMicrosecondCount();

   Print((string)tH, " Hour");
   Print((string)tM, " Minutes");
   Print( "Clock: ", (string)s2, " mics, ", (string)s3, " mics" );
2019.11.15 11:33:04.239 TestScript (EURUSD,M1)  7 Hour
2019.11.15 11:33:04.239 TestScript (EURUSD,M1)  37 Minutes
2019.11.15 11:33:04.239 TestScript (EURUSD,M1)  Clock: 158 mics, 158 mics
 

TimeHourMy, TimeMinuteMy не учитывают переводы стрелок и можно сильно влететь. То есть быстрые, но неверные :-)

 

Что то жесть как быстрые, аж не вериться ))
Возможно новый компилятор делает своё дело.

   long tH = 0;
   long tM = 0;
   
   ulong s2 = GetMicrosecondCount();
   
   for ( long t = 0; t <= 1893446400000000; t++ )
   {
      tH = TimeHourMy(t);
      tM = TimeMinuteMy(t);    
   }

   ulong s3 = GetMicrosecondCount();

   Print((string)tH, " Hour");
   Print((string)tM, " Minutes");
   Print( "Clock: ", (string)s2, " mics, ", (string)s3, " mics" );
2019.11.15 11:52:04.771 TestScript (EURUSD,M1)  21 Hour
2019.11.15 11:52:04.771 TestScript (EURUSD,M1)  20 Minutes
2019.11.15 11:52:04.771 TestScript (EURUSD,M1)  Clock: 182 mics, 182 mics
 
Roman:

Тут как то быстро отрабатывают ...My функции, вообще не затрачивая времени ))

Компилятор просто удаляет этот код, потому что он ничего не делает (все значения известны на этапе компиляции).


Maxim Kuznetsov:

TimeHourMy, TimeMinuteMy не учитывают переводы стрелок и можно сильно влететь. То есть быстрые, но неверные :-)

Каким боком летнее время может повлиять?

Значения я сравнивал на диапазоне 1990-2030 гг, совпадение 100%

 
Andrey Khatimlianskii:

Компилятор просто удаляет этот код, потому что он ничего не делает (все значения известны на этапе компиляции).


А если так, одна микросекунда.

   long tH = 0;
   long tM = 0;   
   
   ulong s2 = GetMicrosecondCount();                          
   
   tH = TimeHourMy(TimeCurrent()); 
   tM = TimeMinuteMy(TimeCurrent());     

   ulong s3 = GetMicrosecondCount();
   
   
   Print((string)tH, " Hour");
   Print((string)tM, " Minutes");
   Print( "Clock: ", (string)s2, " mics, ", (string)s3, " mics" );
2019.11.15 13:09:09.716 TestScript (EURUSD,M1)  12 Hour
2019.11.15 13:09:09.716 TestScript (EURUSD,M1)  9 Minutes
2019.11.15 13:09:09.716 TestScript (EURUSD,M1)  Clock: 158 mics, 159 mics
 

То же самое на MqlDateTime, 1 mics

   long tH = 0;
   long tM = 0;   
   
   ulong s2 = GetMicrosecondCount();                          
   
   tH = TimeHour(TimeCurrent()); 
   tM = TimeMinute(TimeCurrent());     

   ulong s3 = GetMicrosecondCount();
   
   
   Print((string)tH, " Hour");
   Print((string)tM, " Minutes");
   Print( "Clock: ", (string)s2, " mics, ", (string)s3, " mics" );
2019.11.15 13:24:27.454 TestScript (EURUSD,M1)  12 Hour
2019.11.15 13:24:27.454 TestScript (EURUSD,M1)  24 Minutes
2019.11.15 13:24:27.454 TestScript (EURUSD,M1)  Clock: 294 mics, 295 mics
 
Roman:

То же самое на MqlDateTime, 1 mics

Почитайте посты @Renat Fatkhullin про оптимизатор компилятора и про то, как делать замеры.

 
Andrey Khatimlianskii:

Почитайте посты @Renat Fatkhullin про оптимизатор компилятора и про то, как делать замеры.

Так если оптимизатор всё и вся оптимизирует, как тогда сделать замеры?
Вы же сами об этом и спрашивали.
Тогда зацикливать в реал тайм, и выводить в коммент, и смотреть значения.
Ваш вопрос был в непонимании почему у вас получается ноль.
По моему я наглядно показал откуда он берётся.
И замеры лучше делать по отдельности, так как кто его знает, что там решит компилятор.

 
Roman:

Так если оптимизатор всё и вся оптимизирует, как тогда сделать замеры?
Вы же сами об этом и спрашивали.
Тогда зацикливать в реал тайм, и выводить в коммент, и смотреть значения.
Ваш вопрос был в непонимании почему у вас получается ноль.
По моему я наглядно показал откуда он берётся.
И замеры лучше делать по отдельности, так как кто его знает, что там решит компилятор.

Вопрос про 0 был не главный. Это, скорее, констатация факта была. И мне самому лень искать способы обмануть компилятор.

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