8 причин выбрать MetaTrader VPS вместо обычного облачного хостинга - страница 2

 
Renat Fatkhullin #:

Вы считаете единственным методом контроля задержек использование устаревшего на 30 лет Sleep из WinAPI? И на основании этого архаичного архитектурного недостатка IBM PC+Windows системы строите вопрос?

У него чудовищный лимит на основе тикового генератора, который по факту работает с частотой дискретизации до 16 мс. И даже метод его ускорения до 1 мс через timeBeginPeriod(1) разгон мультимедийного таймера не очень помогает.


Поэтому в вопросах точного замера микро и миллисекунд секунд нужно использовать спиновый/ожидающий Sleep:

Обычный Sleep плавает в широких диапазонах от 1000 до 16000 микросекунд, а ожидающий отмеряет точно.

Обычный и дешевый по CPU ресурсам Sleep используется для грубой задержки в режиме "подождать, отдать ресурсы на сторону, мне терять нечего" и не применим в low latency учете. Рациональность такого подхода понять можно - экономится CPU.

В тех местах, где точность критична, все массово используют спиновый/крутящийся режим. В нем поток выполнения/контекст не высвобождается, кванты времени не отдаются и 1 ядро CPU часто загружается на 100%.


Более щадящий CPU метод ожидания можно сделать через недокументированные NtSetTimerResolution / NtDelayExecution функции. Но он, как и timeBeginPeriod, может оказывать негативное влияние на общую систему.

Решение точного замера ожидания в любом случае доступно. Но мы можем добавить дополнительную функцию SleepPrecise(int microseconds) с повышенными затратами CPU.



Теперь о VPS:

  1. детально техническая реализация нашего сервиса описана тут: https://www.mql5.com/ru/vps/best-forex-vps-technology
  2. у нас голый оптимизированный хост в server core edition (Windows без GUI), который несет на себе множество копий урезанных терминалов - это грубо говоря в 50-100 раз по всем ресурсам экономнее провайдерских VPS

    вообще аренда классического дешевого Windows Server + Desktop GUI VPS - это техническое самоубийство, если речь идет о снижении задержек и достаточности ресурсов. по ссылке выше все разжевано

  3. у терминалов вообще нет никакого GUI, никаких графиков и вообще практически ничего нет кроме минимального движка
  4. задержки в терминалах сведены к теоретическому минимуму, так как ничего не мешает MQL4/MQL5 программам работать
  5. ресурсов на каждый терминал в разы больше, чем на любом сравнимом VPS
  6. мы жестко оптимизируем свою инфраструктуру и сеть на низкие задержки

Здравствуйте,

заинтересовался этой паузой

//+------------------------------------------------------------------+
//| Spin sleep                                                       |
//+------------------------------------------------------------------+
void SleepSpin(ulong microseconds)
  {
   ulong start=GetMicrosecondCount();
//---
   while((GetMicrosecondCount()-start)<microseconds)
     {
      // тут желательно nop операции поставить, чтобы разгрузить ядро CPU от 100% загрузки
     }
//---
  }

Нельзя ли уточнить какие nop команды есть в MQL?

Гугл поиск ничего не дал, но встроенный в Гугл ИИ выдал/придумал несуществующие команды и даже историю их жизни ))):

Важно: В более новых версиях MQL (MQL5) команда nop заменена на Empty .

Ни одну из них компилятор не принимает.

Или тут вызов системных DLL имеется в виду? В маркет нe пройдет.
Может сделаете свой SleepMicro() c nop?

 

Ожидание в режиме спинлока так и делается:

void SleepSpin(ulong microseconds)
  {
   ulong start=GetMicrosecondCount();
//---
   while((GetMicrosecondCount()-start)<microseconds)
     {
     }
//---
  }


Вот пример:

void SleepSpin(ulong microseconds)
  {
   ulong start=GetMicrosecondCount();
//---
   while((GetMicrosecondCount()-start)<microseconds)
     {
     }
//---
  }

void OnStart()
  {
//---
   ulong start=GetMicrosecondCount();
   Sleep(1);
   Print(GetMicrosecondCount()-start," microseconds elapsed, 1000 expected, standard,   0% CPU");
//---
   start=GetMicrosecondCount();
   Sleep(150);
   Print(GetMicrosecondCount()-start," microseconds elapsed, 150000 expected, standard,   0% CPU");
//---
   start=GetMicrosecondCount();
   SleepSpin(150000);
   Print(GetMicrosecondCount()-start," microseconds elapsed, 150000 expected, spin wait, 100% CPU");
  }

и результат:

  4460 microseconds elapsed,   1000 expected, standard,    0% CPU
158660 microseconds elapsed, 150000 expected, standard,    0% CPU
150000 microseconds elapsed, 150000 expected, spin wait, 100% CPU

Учтите, что со спинлоком вы гарантированно 1 ядро загоните в 100%. За что могут быть последствия.

Спинлоковые задержки показывают ошибочность подхода в обычных приложениях.

Их используют в исключительных и осознанных случаях, когда четко отдают себе отчет, что делают и сколько ядер выводят из обслуживания. Вместе со спинлоком в рамках realtime/high frequency/low latency задач нужно жестко выставлять affinity mask на одно выбранное ядро, чтобы избежать дисперсии времени реакции.


Сразу отвечу, что на системном уровне железа/процессора/операционки нет экономных методов "подождать X микросекунд". Поэтому - только спинлок и 100% CPU.