MT5 и скорость в боевом исполнении - страница 45

 
Andrey Khatimlianskii:

Нет, у меня на ЦентОС виртуалки крутятся. Но я не компетентен продолжать этот диалог.

Все равно двойная виртуализация.

CentOS -> VirtualBox -> Windows 7


Еще урезание до 2х ядер, когда процессор на 8, кардинально меняет поведение и выделяемые ресурсы шедулера потоков.

Эти 2 ядра придется распределить на неминуемые 1000 потоков даже урезанной Windows 7. Так что терминал гарантированно будет иметь повышенное латенси.

 
Renat Fatkhullin:

Ну вы мастер гонять стресс-тесты без контроля соотносимости и резонности.

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

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

Как микросекунды использовать, когда именно они тормозят?! Вот всего 20 вызовов. Четверть миллисекунды на таком смешном числе вызовов для разных практических задач.

2020.10.06 00:50:44.491 Alert: Time[Test6.mq5 15: for(inti=0;i<20;i++)GetMicrosecondCount();] = 254 mсs.
2020.10.06 00:50:44.491 Alert: Time[Test6.mq5 20: for(inti=0;i<20;i++)GetTickCount();] = 19 mсs.

На придушенном VPS разгонять системный таймер через timeBeginPeriod чревато. Вы просто наоборот повысите затраты CPU:

Иначе давно бы в операционке сделали точные GetTickCount/GetTickCount64 и радовались бесплатной точностью. Но нет, за точность этого таймера придется заплатить.


Ничуть не уступает по скорости GetTickCount. Перешел на его использование на тормозном VPS вместо GetMicrosecondsCount. Загрузка с 50% упала до 2% на реальной торговле.

2020.10.06 00:50:44.491 Alert: Time[Test6.mq5 26: for(inti=0;i<20;i++)winmm::timeGetTime();] = 13 mсs.
 
fxsaber:

Как микросекунды использовать, когда именно они тормозят?! Вот всего 20 вызовов. Четверть миллисекунды на таком смешном числе вызовов для разных практических задач.

А у меня эти 20 вызовов:

   ulong ticks=GetMicrosecondCount();
   for(int i=0; i<20; i++)
      GetMicrosecondCount();
   Print("GetMicrosecondCount: ",GetMicrosecondCount()-ticks);

   ticks=GetMicrosecondCount();
   for(int i=0; i<20; i++)
      GetTickCount();
   Print("GetTickCount: ",GetMicrosecondCount()-ticks);


2020.10.06 01:04:44.068 5555 (CAT.NYSE,M5)      GetMicrosecondCount: 1
2020.10.06 01:04:44.068 5555 (CAT.NYSE,M5)      GetTickCount: 0


Ничуть не уступает по скорости GetTickCount. Перешел на его использование на тормозном VPS вместо GetMicrosecondsCount. Загрузка с 50% упала до 2% на реальной торговле.

Не верю, что замена  GetMicrosecondsCount -> GetTickCount даст в реальной программе. Как теоретически, так и практически нет доказательств.

В стресс-тесте на этих двух функциях запросто такое нарисовать можно. Вы сами делаете вывод, что 48% нагрузки на CPU делал замер микросекунд? И это не стресс-тест? Конечно, он самый.


Про ускорение мультимедийного таймера - это снова стресс тесты без оглядки на общую деградацию производительности. Разгон таск шедулера увеличивает системный оверхед операционки.

 
Renat Fatkhullin:

Все равно двойная виртуализация.

CentOS -> VirtualBox -> Windows 7


Еще урезание до 2х ядер, когда процессор на 8, кардинально меняет поведение и выделяемые ресурсы шедулера потоков.

Эти 2 ядра придется распределить на неминуемые 1000 потоков даже урезанной Windows 7. Так что терминал гарантированно будет иметь повышенное латенси.

Я к этому заключению тоже пришел, спасибо за подтверждение. VirtualBox это зло.
И особенно нужно остерегаться впс, на таком развёртывании, таких полно. 
Только чистая операционка на железе, и лучше Linux.
Хоть и через wine, та же виртуализация, но GUI терминала просто летает без единого лага.
И GetMicrosecondsCount крутится без задержек. 

 
Renat Fatkhullin:

А у меня эти 20 вызовов:

Ну так и у меня это ноль микросекунд! Только на домашней машине.

Не верю, что замена  GetMicrosecondsCount -> GetTickCount даст в реальной программе. Как теоретически, так и практически нет доказательств. 

В стресс-тесте на этих двух функциях запросто такое нарисовать можно. Вы сами делаете вывод, что 48% нагрузки на CPU делал замер микросекунд? И это не стресс-тест? Конечно, он самый.

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

Так вот вылизанный таким образом советник (точнее 20 штук параллельно) грузят домашний комп на 1.5%. А вот VPS на 50+%. Стал копать и обнаружил, что тормозит микросекундный таймер. Соответственно, там, где на домашней машине не срабатывают алерты, на VPS сыпались.


Но и этого мало. Благодаря этой ветке был разработан снепшот-механизм, основа которого в этом.

  ulong Snapshot( const uint &RefreshTime, const MAGIC_TYPE &Magic, bool HistoryInit = false )
  {
    if (SNAPSHOT::SnapshotLifeTime() < RefreshTime)
      return(0);
// ....

  ulong SnapshotLifeTime( void ) const
  {
    static const bool IsTester = ::MQLInfoInteger(MQL_TESTER);

    return(IsTester ? ULONG_MAX : (::GetMicrosecondCount() - this.TimeData)); // Обязуем любой вызов снепшота в Тестере делать полноценным.
  }

Это основа любых снепшотов: если с прошлого снепшота прошло меньше заданного времени - ничего не делаем. Именно этот подход позволяет существенно экономить на ресурсах.

Конечно, время обновления малое - по-умолчанию равно одной миллисекунде. Поэтому используется микросекундный таймер.


Так вот из-за тормозов этого таймера снепшот-механизм разрушался, т.к. делался полноценный снепшот на порядок/два чаще, чем на полноценной машине.


Вот такие пироги от тормозов микросекундого таймера. Зато когда перешел на миллисекундный (а не 16-мс), то все стало летать даже на тормозном VPS.

Про ускорение мультимедийного таймера - это снова стресс тесты без оглядки на общую деградацию производительности. Разгон таск шедулера увеличивает системный оверхед операционки.

Да плевать на эти теории, если на практике выходит колоссальный выигрыш. Возможно, на каких-нибудь играх это и сказывается. Но на VPS это была спасительная соломенка.

 
fxsaber:

Ну так и у меня это ноль микросекунд! Только на домашней машине.

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

Так вот вылизанный таким образом советник (точнее 20 штук параллельно) грузят домашний комп на 1.5%. А вот VPS на 50+%. Стал копать и обнаружил, что тормозит микросекундный таймер. Соответственно, там, где на домашней машине не срабатывают алерты, на VPS сыпались.


Но и этого мало. Благодаря этой ветке был разработан снепшот-механизм, основа которого в этом.

Это основа любых снепшотов: если с прошлого снепшота прошло меньше заданного времени - ничего не делаем. Именно этот подход позволяет существенно экономить на ресурсах.

Конечно, время обновления малое - по-умолчанию равно одной миллисекунде. Поэтому используется микросекундный таймер.


Так вот из-за тормозов этого таймера снепшот-механизм разрушался, т.к. делался полноценный снепшот на порядок чаще, чем на полноценной машине.


Вот такие пироги от тормозов микросекундого таймера. Зато когда перешел на миллисекундный (а не 16-мс), то все стало летать даже на тормозном VPS.

Да плевать на эти теории, если на практике выходит колоссальный выигрыш. Возможно, на каких-нибудь играх это и сказывается. Но на VPS это была спасительная соломенка.

Смотрите как красиво было сказано:

Перешел на его использование на тормозном VPS вместо GetMicrosecondsCount. Загрузка с 50% упала до 2% на реальной торговле.

Вывод напрашивался "все из-за тормозов микросекундного замера, вот какое ускорение".

И вдруг выясняется "я сам из-за логической ошибки делал вычислений на порядок больше". И GetMicrosecondsCount был всего лишь триггером этой ошибки.

Переделка на GetTickCount - это фикс/костыль этой ошибки, причем код фикса не был показан. Потому что там не просто замена  GetMicrosecondsCount -> GetTickCount?

Почему сразу нельзя было это сказать?


Судя по логике ускорение было получено за счет явного загрубления учета (прыжок от микросекунд к миллисекунде) и кратного уменьшения создания снепшотов.
 
До сих пор обдумываю целесообразность снепшота SymbolInfoTick, чтобы реже на такое нарываться.
2020.10.05 12:52:35.963         Alert: Time[NewTicks.mqh 33 in NEWTICKS::GetMarketWatchTick: ::SymbolInfoTick(_Symbol,Tick)] = 599 mсs.
2020.10.05 12:52:45.904         Alert: Time[NewTicks.mqh 33 in NEWTICKS::GetMarketWatchTick: ::SymbolInfoTick(_Symbol,Tick)] = 245 mсs.
2020.10.05 12:52:45.904         Alert: Time[NewTicks.mqh 33 in NEWTICKS::GetMarketWatchTick: ::SymbolInfoTick(_Symbol,Tick)] = 470 mсs.
2020.10.05 12:52:45.904         Alert: Time[NewTicks.mqh 33 in NEWTICKS::GetMarketWatchTick: ::SymbolInfoTick(_Symbol,Tick)] = 722 mсs.
2020.10.05 12:52:45.904         Alert: Time[NewTicks.mqh 33 in NEWTICKS::GetMarketWatchTick: ::SymbolInfoTick(_Symbol,Tick)] = 901 mсs.
2020.10.05 12:52:45.905         Alert: Time[NewTicks.mqh 33 in NEWTICKS::GetMarketWatchTick: ::SymbolInfoTick(_Symbol,Tick)] = 1726 mсs.
2020.10.05 12:53:00.123         Alert: Time[NewTicks.mqh 33 in NEWTICKS::GetMarketWatchTick: ::SymbolInfoTick(_Symbol,Tick)] = 864 mсs.
2020.10.05 12:53:03.218         Alert: Time[NewTicks.mqh 33 in NEWTICKS::GetMarketWatchTick: ::SymbolInfoTick(_Symbol,Tick)] = 112 mсs.
2020.10.05 12:53:04.493         Alert: Time[NewTicks.mqh 33 in NEWTICKS::GetMarketWatchTick: ::SymbolInfoTick(_Symbol,Tick)] = 2134 mсs.
2020.10.05 12:53:10.013         Alert: Time[NewTicks.mqh 33 in NEWTICKS::GetMarketWatchTick: ::SymbolInfoTick(_Symbol,Tick)] = 1826 mсs.
2020.10.05 12:53:13.119         Alert: Time[NewTicks.mqh 33 in NEWTICKS::GetMarketWatchTick: ::SymbolInfoTick(_Symbol,Tick)] = 114 mсs.
2020.10.05 12:53:18.008         Alert: Time[NewTicks.mqh 33 in NEWTICKS::GetMarketWatchTick: ::SymbolInfoTick(_Symbol,Tick)] = 116 mсs.
2020.10.05 12:53:20.010         Alert: Time[NewTicks.mqh 33 in NEWTICKS::GetMarketWatchTick: ::SymbolInfoTick(_Symbol,Tick)] = 1095 mсs.
2020.10.05 12:55:55.033         Alert: Time[NewTicks.mqh 33 in NEWTICKS::GetMarketWatchTick: ::SymbolInfoTick(_Symbol,Tick)] = 359 mсs.

Это на машине, которая 20 советников перемалывает с 1.5% CPU. У которой LatencyMon показыает, что все отлично.

Что-то в архитектуре MT5 дает такие лаги одновременно на все запущенные советники. И ни у одном меня.

 
Renat Fatkhullin:

Переделка на GetTickCount - это фикс/костыль этой ошибки, причем код фикса не был показан. Потому что там не просто замена  GetMicrosecondsCount -> GetTickCount?

Почему сразу нельзя было это сказать?

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

Там, безусловно, стресс-тест. По другому наглядно было не показать.


Представьте себе функцию в виде матрешки. Делается замер внешней матрешки. При этом делаются замеры и внутренних матрешек. По итогу из-за тормозов микросекунд внешние матрешки показывают дикие цифры по длительности выполнения, что вызывает шквал однотипных Алертов. Очевидно же, что 10 микросекунд на один вызов GetMicrosecondsCount - это жутко дорого. Вот и сыпал алертами.


Бесплатный грубый миллисекундный таймер стал выдавать либо 0мкс, либо 1000 мкс, либо 2000 мкс. Это гораздо уменьшило количество Алертов и уменьшило тормоза на вызовах функций таймера.


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


Ну а со снепшотами вообще замечательно. Загрубление, по сравнению с домашней машиной (там микросекунды), не сильное. Но если сравнивать с тем, что было на VPS, как небо и земля.


ЗЫ Мы сейчас говорим о целесообразности наличия в MQL миллисекундного таймера, которого, к сожалению, нет. Без него снепшотить на ВПС не получается.

 
fxsaber:
До сих пор обдумываю целесообразность снепшота SymbolInfoTick, чтобы реже на такое нарываться.

Это на машине, которая 20 советников перемалывает с 1.5% CPU. У которой LatencyMon показыает, что все отлично.

Что-то в архитектуре MT5 дает такие лаги одновременно на все запущенные советники. И ни у одном меня.

Вот мой код и стабильное время отработки: никаких сотен и тысяч микросекунд на 20 графиках параллельно

   MqlTick Tick;
   ulong   ticks=GetMicrosecondCount();
   
   SymbolInfoTick(_Symbol,Tick);
   Print("SymbolInfoTick: ",GetMicrosecondCount()-ticks);


2020.10.06 02:14:18.234	5555 (CADJPY,H1)	SymbolInfoTick: 2
2020.10.06 02:14:18.765	5555 (EURNZD,H1)	SymbolInfoTick: 2
2020.10.06 02:14:19.063	5555 (EURNZD,H1)	SymbolInfoTick: 2
2020.10.06 02:14:19.180	5555 (CADJPY,H1)	SymbolInfoTick: 2
2020.10.06 02:14:19.180	5555 (EURCAD,H1)	SymbolInfoTick: 1
2020.10.06 02:14:19.245	5555 (EURNZD,H1)	SymbolInfoTick: 2
2020.10.06 02:14:19.523	5555 (CHFJPY,H1)	SymbolInfoTick: 1
2020.10.06 02:14:19.659	5555 (EURNZD,H1)	SymbolInfoTick: 2
2020.10.06 02:14:20.037	5555 (CADCHF,H1)	SymbolInfoTick: 2
2020.10.06 02:14:20.037	5555 (EURNZD,H1)	SymbolInfoTick: 2
2020.10.06 02:14:20.137	5555 (EURMXN,H1)	SymbolInfoTick: 2
2020.10.06 02:14:20.138	5555 (EURNOK,H1)	SymbolInfoTick: 2
2020.10.06 02:14:20.226	5555 (EURNZD,H1)	SymbolInfoTick: 2
2020.10.06 02:14:20.227	5555 (CHFJPY,H1)	SymbolInfoTick: 2
2020.10.06 02:14:20.525	5555 (AUDNZD,H1)	SymbolInfoTick: 1
2020.10.06 02:14:20.645	5555 (EURNZD,H1)	SymbolInfoTick: 2
2020.10.06 02:14:20.919	5555 (EURNZD,H1)	SymbolInfoTick: 2
2020.10.06 02:14:21.123	5555 (EURNZD,H1)	SymbolInfoTick: 1
2020.10.06 02:14:21.129	5555 (EURAUD,H1)	SymbolInfoTick: 2
2020.10.06 02:14:21.234	5555 (EURNOK,H1)	SymbolInfoTick: 1
2020.10.06 02:14:21.441	5555 (EURAUD,H1)	SymbolInfoTick: 2
2020.10.06 02:14:22.299	5555 (EURNZD,H1)	SymbolInfoTick: 2
2020.10.06 02:14:22.383	5555 (AUDNZD,H1)	SymbolInfoTick: 2


Сколько у вас ядер и какой процессор? i7-2600?

Снова скрытый стресс-тест с миллионами запросов параллельно?


Будьте прозрачнее. То, что вы опубликовали пару простых _B вызовов, не является доказательством ваших остальных заявлений. Вы резко забываете про код и реальное описание условий, как только делаете запредельные заявления.

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

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

 
fxsaber:

ЗЫ Мы сейчас говорим о целесообразности наличия в MQL миллисекундного таймера, которого, к сожалению, нет. Без него снепшотить на ВПС не получается.

Миллисекундный таймер давно есть: EventSetMillisecondTimer()

Документация по MQL5: Работа с событиями / EventSetMillisecondTimer
Документация по MQL5: Работа с событиями / EventSetMillisecondTimer
  • www.mql5.com
Указывает клиентскому терминалу, что для данного эксперта или индикатора необходимо генерировать события таймера с периодичностью менее одной секунды. нужно получать события таймера чаще, чем один раз в секунду. Если вам достаточно обычного таймера с периодом более 1 секунды, то используйте EventSetTimer(). В тестере стратегий используется...
Причина обращения: