// Возвращает true в некоторых ситуациях, когда чарт не виден. bool IsInvisible( long chartID = 0 ) { bool Res = ::ChartGetInteger(chartID, CHART_IS_MINIMIZED); if (!Res && !::ChartGetInteger(chartID, CHART_IS_MAXIMIZED) && ::ChartGetInteger(chartID, CHART_IS_DOCKED)) { if (!chartID) chartID = ::ChartID(); for (long Chart = ::ChartFirst(); (Chart != -1) && !Res; Chart = ::ChartNext(Chart)) Res = (Chart != chartID) && ::ChartGetInteger(Chart, CHART_IS_MAXIMIZED); } return(Res); }
На первый взгляд кажется, что Benchmark-библиотека не при чем. Но добавим альтернативный вариант той же функции.
#include <fxsaber\MultiTester\MTTester.mqh> // https://www.mql5.com/ru/code/26132 // Возвращает true в некоторых ситуациях, когда чарт не виден. // Учитывает еще окно Терминала и графики Оптимизатора. bool IsInvisible2( const long chartID = 0 ) { static const long TerminalHandle = MTTESTER::GetTerminalHandle(); static const long ChartsHandle = user32::GetDlgItem(TerminalHandle, 0xE900); bool Res = ::ChartGetInteger(chartID, CHART_IS_MINIMIZED) || user32::IsIconic(TerminalHandle); if (!Res && !::ChartGetInteger(chartID, CHART_IS_MAXIMIZED) && ::ChartGetInteger(chartID, CHART_IS_DOCKED)) { const long hwnd = ::ChartGetInteger(chartID, CHART_WINDOW_HANDLE); for (long handle = user32::GetWindow(ChartsHandle, GW_CHILD); handle && !Res; handle = user32::GetWindow(handle, GW_HWNDNEXT)) Res = (hwnd != handle) && user32::IsZoomed(handle); } return(Res); }
И сравним их показатели и производительность.
#include <fxsaber\Benchmark.mqh> // https://www.mql5.com/ru/code/31279 #define _B2(A) _B(A, 1) const bool Init = EventSetTimer(1); void OnTimer() { Alert((string)_B2(IsInvisible()) + " - " + (string)_B2(IsInvisible2())); }
Результат.
2020.10.02 00:30:51.114 Alert: Time[Test9.mq5 46 in OnTimer: IsInvisible()] = 877 mсs. 2020.10.02 00:30:51.114 Alert: Time[Test9.mq5 46 in OnTimer: IsInvisible2()] = 3 mсs. 2020.10.02 00:30:51.114 Alert: true - true 2020.10.02 00:30:52.116 Alert: Time[Test9.mq5 46 in OnTimer: IsInvisible()] = 1117 mсs. 2020.10.02 00:30:52.116 Alert: Time[Test9.mq5 46 in OnTimer: IsInvisible2()] = 14 mсs. 2020.10.02 00:30:52.116 Alert: true - true 2020.10.02 00:30:53.123 Alert: Time[Test9.mq5 46 in OnTimer: IsInvisible()] = 1939 mсs. 2020.10.02 00:30:53.123 Alert: Time[Test9.mq5 46 in OnTimer: IsInvisible2()] = 5 mсs. 2020.10.02 00:30:53.123 Alert: true - true 2020.10.02 00:30:54.121 Alert: Time[Test9.mq5 46 in OnTimer: IsInvisible()] = 1082 mсs. 2020.10.02 00:30:54.121 Alert: Time[Test9.mq5 46 in OnTimer: IsInvisible2()] = 4 mсs. 2020.10.02 00:30:54.121 Alert: true - true 2020.10.02 00:30:55.121 Alert: Time[Test9.mq5 46 in OnTimer: IsInvisible()] = 1455 mсs. 2020.10.02 00:30:55.121 Alert: Time[Test9.mq5 46 in OnTimer: IsInvisible2()] = 15 mсs. 2020.10.02 00:30:55.121 Alert: true - true 2020.10.02 00:30:56.119 Alert: Time[Test9.mq5 46 in OnTimer: IsInvisible()] = 1024 mсs. 2020.10.02 00:30:56.119 Alert: Time[Test9.mq5 46 in OnTimer: IsInvisible2()] = 5 mсs. 2020.10.02 00:30:56.119 Alert: true - true
Становится понятно, что альтернативный вариант гораздо быстрее. И если боевой советник может использовать DLL, то лучше не использовать чистый MQL-вариант.
Пробуем выяснить, где загвоздка у штатного варианта. Прописываем в исходный код несколько символов.
for (long Chart = _B2(::ChartFirst()); (Chart != -1) && !Res; Chart = _B2(::ChartNext(Chart))) Res = (Chart != chartID) && _B2(::ChartGetInteger(Chart, CHART_IS_MAXIMIZED));
И сразу видим причину.
2020.10.02 00:45:14.113 Alert: Time[Test9.mq5 36 in IsInvisible: ::ChartGetInteger(Chart,CHART_IS_MAXIMIZED)] = 878 mсs. 2020.10.02 00:45:14.114 Alert: Time[Test9.mq5 36 in IsInvisible: ::ChartGetInteger(Chart,CHART_IS_MAXIMIZED)] = 943 mсs. 2020.10.02 00:45:14.114 Alert: Time[Test9.mq5 36 in IsInvisible: ::ChartGetInteger(Chart,CHART_IS_MAXIMIZED)] = 297 mсs. 2020.10.02 00:45:14.116 Alert: Time[Test9.mq5 36 in IsInvisible: ::ChartGetInteger(Chart,CHART_IS_MAXIMIZED)] = 1787 mсs. 2020.10.02 00:45:14.116 Alert: Time[Test9.mq5 35 in IsInvisible: ::ChartNext(Chart)] = 2 mсs. 2020.10.02 00:45:14.117 Alert: Time[Test9.mq5 36 in IsInvisible: ::ChartGetInteger(Chart,CHART_IS_MAXIMIZED)] = 980 mсs. 2020.10.02 00:45:14.117 Alert: Time[Test9.mq5 35 in IsInvisible: ::ChartNext(Chart)] = 2 mсs. 2020.10.02 00:45:14.117 Alert: Time[Test9.mq5 36 in IsInvisible: ::ChartGetInteger(Chart,CHART_IS_MAXIMIZED)] = 59 mсs. 2020.10.02 00:45:14.118 Alert: Time[Test9.mq5 36 in IsInvisible: ::ChartGetInteger(Chart,CHART_IS_MAXIMIZED)] = 803 mсs. 2020.10.02 00:45:14.119 Alert: Time[Test9.mq5 36 in IsInvisible: ::ChartGetInteger(Chart,CHART_IS_MAXIMIZED)] = 1059 mсs.
CHART_IS_MAXIMIZED тормозит для чужих чартов. Баг-репорт готов! С библиотекой это было очень просто.
Из-за тормозов GetMicrosecondCount перелопатил другие варианты. В итоге остановился на одном, результативность которого исследовал с помощью библы.
#include <fxsaber\Benchmark\Benchmark.mqh> // https://www.mql5.com/ru/code/31279 #import "winmm.dll" uint timeGetTime( void ); // Альтернативный счетчик времени. #import ulong GetNextCount( void ) { uint TickCount = 0; const uint PrevTickCount = winmm::timeGetTime(); do { TickCount = winmm::timeGetTime(); } while ((TickCount == PrevTickCount)); return(TickCount - PrevTickCount); } const bool Init = EventSetTimer(1); // Синхронизация void OnTimer() { GetNextCount(); // Синхронизация Print("winmm::timeGetTime Step = " + (string)(_B(GetNextCount(), 1) * 1000) + " mcs."); }
Результат.
Alert: Time[Test9.mq5 117 in OnTimer: GetNextCount()] = 999 mсs. winmm::timeGetTime Step = 1000 mcs. Alert: Time[Test9.mq5 117 in OnTimer: GetNextCount()] = 998 mсs. winmm::timeGetTime Step = 1000 mcs. Alert: Time[Test9.mq5 117 in OnTimer: GetNextCount()] = 999 mсs. winmm::timeGetTime Step = 1000 mcs. Alert: Time[Test9.mq5 117 in OnTimer: GetNextCount()] = 998 mсs. winmm::timeGetTime Step = 1000 mcs. Alert: Time[Test9.mq5 117 in OnTimer: GetNextCount()] = 996 mсs. winmm::timeGetTime Step = 1000 mcs. Alert: Time[Test9.mq5 117 in OnTimer: GetNextCount()] = 996 mсs. winmm::timeGetTime Step = 1000 mcs.
Отлично видно, насколько точен альтернативный миллисекундый счетчик времени. Можно использовать, т.к. еще и не тормозит (проверял).

- Arno Lentfer
- www.windowstimestamp.com
Из-за тормозов GetMicrosecondCount перелопатил другие варианты. В итоге остановился на одном, результативность которого исследовал с помощью библы.
Результат.
Отлично видно, насколько точен альтернативный миллисекундый счетчик времени. Можно использовать, т.к. еще и не тормозит (проверял).
никогда не пользовался
#import "winmm.dll" uint timeGetTime( void ); // Альтернативный счетчик времени. #import
а QueryPerformanceCounter когда то использовал https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter
суть - получаете значение таймера <1 мкс
вроде работает, нагуглил https://stackoverflow.com/questions/1739259/how-to-use-queryperformancecounter
портировал:
#import "Kernel32.dll" bool QueryPerformanceCounter(long &lpPerformanceCount); bool QueryPerformanceFrequency(long &lpFrequency); #import double PCFreq = 0.0; long CounterStart = 0; //+------------------------------------------------------------------+ void StartCounter() { long li; if(!QueryPerformanceFrequency(li)) Print("QueryPerformanceFrequency failed!"); PCFreq = double(li) / 1000.0; QueryPerformanceCounter(li); CounterStart = li; } //+------------------------------------------------------------------+ double GetCounter() { long li; QueryPerformanceCounter(li); return double(li - CounterStart) / PCFreq; } //+------------------------------------------------------------------+ void OnStart() { StartCounter(); Sleep(1000); double result = GetCounter(); Print("Sleep(1000) выполнялся ", result, " мс"); } //+------------------------------------------------------------------+
никогда не пользовался
а QueryPerformanceCounter когда то использовал https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter
суть - получаете значение таймера <1 мкс
вроде работает, нагуглил https://stackoverflow.com/questions/1739259/how-to-use-queryperformancecounter
портировал:
Также реализован GetMicrosecondsCount.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
MT5 и скорость в боевом исполнении
fxsaber, 2020.10.04 11:22
Пробовал заменить на WinAPI-вариант.
Результат идентичный штатному. Видимо, внутренняя реализация такая же. Есть какая-то другая реализация замера в микросекундах?
Поэтому не подходит.
Также реализован GetMicrosecondsCount.
Поэтому не подходит.
не так
QueryPerformanceCounter - это счетчик тактов процессора
а QueryPerformanceFrequency - это константное значение от Виндовс, которое знает расчетную производительность Вашего ПК
тут в общем вопрос - в чем Вы хотите более точно замерять производительность ПК?
- в тактах ЦПУ - величина не постоянная, зависит от загрузки и от самого ЦПУ, как он умеет использовать режим энергосбережения - он попросту может не успевать загрузить все ядра и поднять внутреннюю частоту на небольших по времени выполнения задачах
- в значениях точного времени микросхемы системного таймера, она не зависима от ЦПУ, но если не ошибаюсь, то там потолок точности миллисекунды... погуглить нужно
UPD: кажется GetSystemTimePreciseAsFileTime это системное время https://stackoverflow.com/questions/34557407/queryperformancecounter-or-getsystemtimepreciseasfiletime-when-using-sntp
не так
Вчера много часов потратил на изучение вопроса и эксперименты. GetMicrosecondsCount реализован через QPC, который вызывает тормоза на некоторых машинах.
Искался вариант замерителя без тормозов. Нашелся с миллисекундным квантованием.
Вчера много часов потратил на изучение вопроса и эксперименты. GetMicrosecondsCount реализован через QPC, который вызывает тормоза на некоторых машинах.
Искался вариант замерителя без тормозов. Нашелся с миллисекундным квантованием.
возможно так и есть, не занимался этим вопросом
но
меньше чем такт процессора, имхо, не существует дискретности для измерения производительности ПК
поэтому и предлагаю в тактах мерять производительность, т.е. используйте просто QueryPerformanceCounter - который выдаст текущий счетчик количества тактов тактов ЦПУ
проблема одна - значение будет сильно плавать, что довольно неудобно, но это будет точное значение сколько выполнялся код на конкретном ПК
Igor Makanu:
используйте просто QueryPerformanceCounter - который выдаст текущий счетчик количества тактов тактов ЦПУ
Вы меня не слышите. Эта функция тормозит на некоторых машинах - факт. Почему так происходит - не копал.
Предлагал проверить свои VPS. Отклика не было.
Вы меня не слышите. Эта функция тормозит на некоторых машинах - факт. Почему так происходит - не копал.
понял, тогда жаль
это видимо от материнки зависит, по крайней мере на старом ноутбуке можно было подразогнать его с помощью правки в БИОСе частоты шины материнки, что влияло на точность системного таймера
ЗЫ: тут хорошо описана в комментариях привязка к QPC https://overcoder.net/q/1177931/%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%82%D0%B0%D0%B9%D0%BC%D0%B5%D1%80%D0%B0-c-clock-%D0%BF%D1%80%D0%BE%D1%82%D0%B8%D0%B2-qpc-winapi-%D0%B8%D0%BB%D0%B8-timegettime
Вы меня не слышите. Эта функция тормозит на некоторых машинах - факт. Почему так происходит - не копал.
Предлагал проверить свои VPS. Отклика не было.
вот тесты на ВПС , вроде такая же ситуация
http://demin.ws/blog/russian/2009/03/05/queryperformancecounter-on-multicore-and-virtual-systems/

- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Benchmark:
Измерение времени выполнения функций/методов, выражений и частей кода.
Автор: fxsaber