Блог им. ANTI_Finsov

Загрузка процессора на 100% от запущенного скрипта lua. Что делать?...

Коллеги, Всем добрый день!

Раньше не приходилось работать с lua.  Но здесь накатал небольшой скрипт в рамках которого происходит запросы текущей цены инструмента и запись её файл и столкнулся с проблемами производительности.
До запуска скрипта  доля нагрузки Quik-a на процессор составляла порядка 2%.
После запуска скрипта нагрузка на процессор увеличилась до 30%.   На рабочем компьютере все работает, но вот на виртуалке, где производительность ниже, всё виснет.
Ребят кто сталкивался с подобным и возможно ли оптимизация данной ситуации?

Скрипт скрипта прилагаю, но не думаю, что в нём проблема:

local stopped=false
local FileNameRead=getScriptPath().."\\poz.txt"
local FileNameWrite=getScriptPath().."\\data.txt"
local FileRead
local ID
local code
FileRead=io.open(FileNameRead,«r»)
local Read
code,ID=FileRead:read(4,"*n")
FileRead:close()
--message(code)
local ID_back=ID
local direct

function OnStop()
stopped=true
return 5000
end


function main()

local TableSI=AllocTable()
AddColumn(TableSI,1,«Дата»,true,QTABLE_DATE_TYPE,10)
AddColumn(TableSI,2,«Время»,true,QTABLE_TIME_TYPE,10)
AddColumn(TableSI,3,«Код»,true,QTABLE_STRING_TYPE,10)
AddColumn(TableSI,4,«Цена»,true,QTABLE_INT_TYPE,10)
AddColumn(TableSI,5,«Позиция»,true,QTABLE_INT_TYPE,10)

while stopped==false do
local ServerTime=tostring(getInfoParam(«SERVERTIME»))
local TradeDate=tostring(getInfoParam(«TRADEDATE»))
local SecCode=«SiH9»
local LastPrice = getParamEx(«SPBFUT», SecCode, «LAST»).param_value
local Pos=getFuturesHolding(«SPBFUT»,«SPBFUT00d8u»,SecCode,0)
if Pos~=nil then
Pos=Pos.totalnet
else
Pos=0
end
FileRead=io.open(FileNameRead,«r»)
local Read
code,ID,Read=FileRead:read(4,"*n","*n")
FileRead:close()
if(Read~=nil) then
if ID_back~=ID then
local Price
if (Read>0) then
Price=tonumber(LastPrice-LastPrice%1)*(-1)*Read
direct=1
elseif (Read<0) then
Price=tonumber(LastPrice-LastPrice%1)*math.abs(Read)
direct=-1
end
local FileWrite=io.open(FileNameWrite,«a»)
if Price~=nil then
FileWrite:write(tostring(Price).." ")
FileWrite:close()
end
sleep(1000)
ID_back=ID
end

end
end
message(«Скрипт остановлен»)
end

 

3.8К | ★9
33 комментария
У вас похоже sleep не там стоит. Поставьте его перед end, завершающем «while stoped»
А если это по задумке, то поставьте там хотя бы sleep( 0 ), это капитально снизит нагрузку на процессор.
Если sleep в цикле функции main не выполняется, то скрипт будет полностью съедать одно ядро процессора.
avatar
Работа с файлом в Мэйн в каждом цикле? Экспэнсив!
avatar
bocha, да в каждом, получается в этом проблема?
avatar
ANTI_Finsov, ну мэйн же просто крутится в безусловном цикле с задержкой. Сильно рачительные люди его стараются не нагружать, а условно инициированные действия совершать по колбэкам, ну или хотя бы по If через изменение Global
Попробуйте поэкспериментировать в этом направлении, должно помочь
avatar
bocha, да скорее всего в этом проблема
avatar
ANTI_Finsov, 
получается в этом проблема?
а чего гадать, закомментируете, да посмотрите
avatar
смирись… LUA машина кушает один поток и все.
avatar
самый тупой и простой метод отладки:

1. последовательно комментите функции и прогоняете скрипт.
2. смотрите, какая функция вызывает загруз проца
3. чешете репу
4. пишите на СЛ вопрос, если расчесали до крови, а толку — ноль
avatar
Сергей Симонов, проблему уже решил.  Слишком загрузил main. Вынес всё в отдельную функцию и проблема решена.
avatar
ANTI_Finsov, но функция запускается в main? или как?
avatar
Igr, да просто вынес её за main.
function main()
   while running do
     my_function()
      sleep(1000)
   end
end
avatar

ANTI_Finsov, а есть разница разве? она ж всё равно запускается а значит и всё что в этой функуции прописано запускается тоже

 

avatar
Igr, по идеи Вы правы. Но мне это помогло. Нагрузка снизилась с 30% до 3.
avatar
ANTI_Finsov, ну у вас же sleep был в этой функции, а теперь вы его вынесли за функцию, в этом была проблема по моему 
avatar

ANTI_Finsov, по моему не в этом ошибка, у вас sleep(1000) был после if, т.е возможно срабатывал только иногда, а когда нет то получается sleep(1000) вообще не работал, а значит main() выполнялся с частотой раз в миллисекунду  

мне так кажется, вот и загружал комп по полной 

avatar
Первое правило скриптов QLua: 
Функция Main() ВСЕГДА должна выглядеть примерно так:

function main()
   while running do
      sleep(Freq)
   end
end

где Freq — задержка в миллисекундах.

В зависимости от конкретных задач работа скрипта строится или на вызове определенных функций колбэками или на бесконечном цикле, определенном вне main(). В ряде случаев работа через колбэки может приводить к очень большой нагрузке на процессор, и сопровождаться значительной потерей производительности терминала.

Если и когда захотите одновременно запускать пару десятков скриптов (торговых роботов) — быстро поймете, что QLua Вам уже не подходит. Да и гибкости часто не хватает.
Если есть возможность — лучше сразу начинайте смотреть в сторону C#.

Да, совсем забыл!!!
quik2dde.ru/index.php

Это на тот случай, если все же хотите продолжить поглубже изучать QLua.

avatar

Prophetic, а где делать все вычисления если не в main? 

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

avatar
Igr, В идеале — в отдельных функциях, которые вызываются колбэками.
Проблема обычно в том, что тот же колбэк «OnAllTrade», по которому мы определяем изменение цены последней сделки по интересующему нас инструменту, вызывается слишком часто, и при сложной логике мы не успеваем выполнить полный расчет до поступления следующего колбэка.
Когда я писал роботов на QLua, то вынужден был делать main() достаточно насыщенным различными командами, и это приводило к высокой нагрузке на процессор и терминал начинал сильно тормозить (не забываем, что и терминал и все скрипты работают в одном потоке).
Данная проблема частично решалась увеличением задержки в конце каждого цикла, но все равно со временем я «уперся в потолок» максимальной нагрузки, и вынужден был начать поиски способа перехода на C# (с параллельным изучением этого языка). Уже года 3 на QLua роботов не пишу. Теперь только на C#.
avatar
Prophetic, ну я цены из стакана беру, все расчёты сравнения в майн, когда в колбеках делал какие то расчёты вот тогда терминал подвисал не хило, когда перенёс всё в майн стало намного лучше, ну у меня 1 скрипт всего лишь работает, проц на 25% загружает, частота расчётов большая 
avatar
Igr, 
1. В самих колбэках конечно же ничего делать нельзя. Только проверку на то, что это именно тот колбэк который Вы ждете, и в случае положительного результата — вызов нужной функции.
2. В стакане нет информации о цене последней сделки по инструменту. только заявки спроса и предложения. Для ликвидных бумаг это не сильно принципиально, но во многих случаях это только заявки. Сделки — это совсем другая история. Но тут каждый сам решает, что ему нужно.
3. На нескольких скриптах (до 10), при правильной организации структуры, потери терпимы. Я больше десятка роботов держал с визуальными интерфейсами каждый. Но нужно помнить, что критическая ошибка в одном роботе может привести к крэшу всего терминала, со всеми вытекающими последствиями. При любых раскладах, логика работы робота за пределами процесса терминала — это только благо. Но пока лично не столкнетесь с этими проблемами, понять меня будет непросто.
avatar

Prophetic, 

1. но вот вызов нужной функции, ведь эта функция будет ыполнятся именно в колбэке, т.е. если функция выполняется долго то всё зависнит, так ведь? 

3. да всё логично, вполне понятно)  

 

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

avatar
Igr, 
1. Досконально не проверял, но общая суть верна. Можете попробовать немного обмануть систему, запрещая выполнять какую-либо обработку данных в колбэке, пока не завершилась работа функции от предыдущего вызова.

Фактически — никаких преимуществ, с точки зрения производительности, нет. Только проблемы. Для HFT квик все равно не годится, а для всех прочих задач грамотный коннектор обеспечивает достаточное быстродействие, чтобы вообще не задумываться о скорости обмена информацией между роботом и терминалом.
Скажем так: QLua хорош на начальном этапе освоения роботостроения (в области биржевой торговли). Написав пару десятков роботов на этом языке, и освоив начальный уровень программирования на C#, можно достаточно быстро и без особых проблем перейти на С#.
Я потратил несколько месяцев на самостоятельное изучение C#, а примерно через полгода, после того как нашел коннектор, написал первого полноценного робота на этой платформе.
avatar

Prophetic, разве HFT не торгуют через квик? 

а через что? 

avatar
Igr, для HFT на первом месте стоит скорость получения данных и вывод собственных заявок на площадку. Ни одна связка квик-брокер-биржа не может обеспечить достаточную скорость (в нынешних реалиях).
Для HFT используют прямое подключение к бирже (например Plaza), вплоть до установки своих серверов в стойку, которая расположена максимально близко к серверам биржи. На сегодняшний день HFT — это удел достаточно серьезных игроков, которые вкладывают очень большие деньги в инфраструктуру. Для простых одиночек эта область стала практически недоступна (раньше, конечно, было не так).
avatar
Prophetic, а прямое подключение идёт без квика вообще? там же какой то должен быть терминал? 
avatar
Igr, Сами позиции вы можете контролировать через терминал, но робот работает совершенно отдельно. И не через QUIK. Во всяком случае не через клиентские терминал QUIK, с которым вы обычно работаете. Прямой коннект по протоколу биржи или через стандартизованный для этого дела протокол FIX
avatar
Igr, Да, без квика вообще. И терминала там никакого нет. Есть программный доступ к определенному набору данных (примерно таких же как в квике). Вы эти данные можете обрабатывать как угодно, а на биржу только отправляете транзакции на выставление или удаление заявок.
Это сильно упрощенное объяснение.
Вот, можете почитать, если интересно: https://www.moex.com/s444

avatar

Prophetic, понятно, спасибо 

но как это вообще выглядит, вот у вас робот написан на си под квик, как вы его подключаете к PLAZAII ?  а если на клуа писан его вообще не получится использовать? 

avatar
Igr, Робот, который написан на C# по квик, подключается к терминалу через специальную программу-коннектор (в моем случае QUIKSharp).
Что касается плазы, то до практической реализации я не доходил (не возникло необходимости), но предполагаю, что подходи будет похожим, т.е. надо будет написать программу-коннектор, которая будет подключаться к серверу и транслировать данные вашим роботам, а роботы, соответственно, будут получать данные от этого коннектора, обрабатывать их и через него же отправлять транзакции на сервер.
Робот, написанный на QLua никак нельзя подключить к плазе (во всяком случае, мне неизвестны такие способы).
avatar
Prophetic, спасибо 
avatar
Поток бесконечно выполняется не задерживаясь ни на милисекунду.
надо давать ему поспать когда нет работы )
avatar
Про устройство QLua и как оно функциклирует в рамках терминала QUIK можно почитать тут
quik2dde.ru/viewtopic.php?id=16
avatar
Вы пишете, что процессор загружен на 100%. В смысле весь процессор (а не одно ядро) загружен на 100%? У вас может одноядерный процессор? это экзотика по нашим временам
avatar

Читайте на SMART-LAB:
Облигации на пальцах: как устроен главный инструмент инвестора
Если у вас все еще нет облигаций в портфеле — вы либо неверно инвестируете, либо не совсем понимаете, зачем они нужны и по какому принципу...
Фото
Каждый инвестор желает знать, где сидит доходность? Взгляд Goldman Sachs на инвестиции до конца года
Если вы инвестируете свой капитал на фондовом рынке, то каждый год легко может принести вам как большие потери, так и несметные богатства....
Опыт Х5: Как меняются программы лояльности в ритейле
Наш управляющий директор «Х5 Клиентский опыт» Михаил Ярцев в интервью Ведомостям подробно рассказал, как в текущих реалиях меняется поведение...
Фото
Башнефть: есть шанс на переоценку, но нужно запастись терпением. Прогноз сошелся с фактом в высокой точностью, ищем инвест идею
Башнефть отчиталась по МСФО за 2025 год — внимание, квартальных отчетов в прошлом году не было вообще! Традицицинно сравниваем прогноз...

теги блога ANTI_Finsov

....все тэги



UPDONW
Новый дизайн