Где реакция поддержки? ---- Третий раз (первый комментарий был написан 10.09.2021 07:46:28 обращаю внимание поддержки на то, что тест, выложенный 10.09.2021 07:46:28 в данной ветке, в QUIK (8.13.1.16, 9.1.3.11 и 9.2.1.4 (с последними обновлениями), в QLua 5.3 демонстрирует ошибку в запусках колбеков. Это подтверждено пользователем Anton (смотрите комментарий 61). Если перевести на простой язык, то диагностируется ошибка синхронизации выполнения потока запуска колбеков и потока main скрипта (и это после полутора года эксплуатации новых версий QUIK ). Ошибки синхронизации могут проявляться как случайные сбои в сриптах пользователей в различные моменты времени. Что из выше написанного не понятно? А если непонятно, то где вопросы?
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
13.09.2021 11:46:49
Просьба (повторная) к поддержке: довести содержимое моего комментария: до разработчиков QUIK. В QUIK 9.2.1.4 (с последними обновлениями) тестовый скрипт, выложенный в упомянутом выше комментарии, демонстрирует, по моему мнению, ошибку в запусках колбеков, в QLua 5.3 ( в QLua 5.4 эта ошибка не диагностируется, но это не означает, что в 5.4 такой ошибки нет).
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
11.09.2021 07:59:05
Цитата
Anton написал: TGB , у меня для вас две новости, как водится: 1) в 5.3 воспроизводится буквально сразу, запущено 4 скрипта и заказаны все параметры по всем инструментам (на боевом); 2) в 5.4 в тех же условинях НЕ ВОСПРОИЗВОДИТСЯ.
Действительно, в Qlua 5.4 тест ошибку не диагностирует. --- Спасибо Антону за его уточнение. -- А где поддержка?
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
10.09.2021 13:04:09
Цитата
Anton написал: Все такое же, имена поменяйте. Там может вообще темплейт в сорце.
Имена я способен поменять, но мы же обсуждаем не то что я могу сделать, а как это сделано в текущем QLua.
Цитата
Anton написал: Это значит, что коллектор начинает агрессивничать и влезать в любую доступную дыру. Где он там дыру в мейне нашел, науке пока неизвестно.
В принципе, если обеспечено четкое разделение между потоками, среды исполнения Lua (то есть, она разделяемый ресурс с корректной синхронизацией доступа к ней) то это эквивалентно однопоточному Lua, в котором ошибки, конечно есть, но их мало.
Что то, не сильно, похоже на детали. Например, не охватывается случай "OnParam". А как вы обясните:
Цитата
Anton написал: в 5.3 воспроизводится буквально сразу, запущено 4 скрипта и заказаны все параметры по всем инструментам (на боевом
----
Цитата
Anton написал: Это lua_lock() + lua_getglobal() + lua_unlock(), совершенно бессмысленно это проделывать, точно зная, что в скрипте нет такой функции. Дискутировать лень.
Ну, конечно, вместо lua_getglobal(...) (кстати, lua_lock() и lua_unlock() выполняется внутри функции lua_getglobal), эквивалентной с точки зрения времени обращения, обращению к глобальной переменной, даже если этой переменной не существует, можно заняться более содержательным алгоритмом регистрации колбеков скриптов (где можно и ошибиться - замечательная возможность).
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
10.09.2021 11:31:32
Цитата
Anton написал: в 5.3 воспроизводится буквально сразу, запущено 4 скрипта и заказаны все параметры по всем инструментам (на боевом);
Все-таки, воспроизводится. ----
Цитата
Anton написал: в 5.4 в тех же условинях НЕ ВОСПРОИЗВОДИТСЯ.
Ну. тогда АРКИ надо объявить, что в версия QLua 5.3 не работоспособна. ---
Цитата
Anton написал: колбеки так и запускаются, плюс-минус детали.
Раскажите детали. Мне это было бы интересно.
Цитата
Anton написал: Если не был объявлен, квик его не будет дергать. Очень даже хорошая оптимизация, иначе квик бы на каждое событие разыскивал необъявленные функции во всех скриптах, что несколько затратно, учитывая локи.
Вы, наверное, знаете, что обращение lua_getglobal (<Основной State в котором запускается колбек>, <Имя колбека>) это эквивалентно обращение в тексте скрипта к переменной скрипта (тоесть. выполняется быстро). Это же обращение к полю таблицы. Или вы думаете, что это не так? Тогда подискутируем. А если это так, то о каком "разыскивании по всем скриптам" идет речь, когда происходит обращение к глобальной таблице, определяемой <Основной State в котором запускается колбек>. Вообще то, мне было бы интересно пообщаться с главным разработчиком QUIK. Но вы же, похоже не главный?
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
10.09.2021 10:39:27
Поддержка понимает, что пока не будут устранены "кривые, мерцающие, редкие" ошибки QLua, на нее будет постоянно валиться вал разнообразных ошибок из различных функциональностей QLua? Если бы я был разработчиком QLua, то в первую очередь занимался бы устранением именно "кривых" ошибок. Это глобальные ошибки, которые могут проявляться у пользователя в любых местах его скриптов, вводя в заблуждения относительно источника ошибок.
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
10.09.2021 09:47:35
Я не очень понимаю в чем могут быть проблемы запуска колбеков QLua. Вот вариант как это можно сделать просто ( C-API Lua):
Код
if ( lua_getglobal (<Основной State в котором запускается колбек>, <Имя колбека>) == LUA_TFUNCTION) // запись и проверка переменной колбека скрипта в стек
{
if ( lua_pcall(<Основной State в котором запускается колбек>, <Количество параметров колбека>, <Список параметров колбека>) ~= 0 ) // запуск колбека
{
<Обработка ошибки при запуске колбека>
}
}
else // в переменной колбека не функция
{
<Обработка ошибки пользователя, задавшего в качестве колбека не функцию>
}
Этот вариант обеспечивает возможность (отсутствующую в существующей версии QLua) замены пользователем функции, вызываемой в качестве колбека, при исполнении скрипта.
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
10.09.2021 07:46:28
Просьба к поддержке довести содержимое этого комментария до разработчиков QUIK. ----- В версиях QUIK (8.13.1.16 и 9.1.3.11), похоже, есть ошибка, демонстрируемая кодом скрипта, который выложен в комментарии далее. Этот скрипт появился в результате анализа редко возникающей «мерцающей» ошибки (похожей на ошибки QLua, описанные Старателем в данной ветке), когда в переменной сразу после присвоения ей значения, это значение на следующем шаге оказывалось искаженным. При одновременном запуске трех экземпляров скриптов в QUIKе, подключенного к учебному серверу, в разные моменты времени, но достаточно часто (~ c 10 минутным ин-тервалом) выдается сообщение о том, что параллельно (одновременно) выполняются байт-код потока колбека и байт-код потока main (смотрите текст скрипта). В существующей реализации QLua такого быть не должно. Можно предположить, что в QLua есть ошибка в реализации запуска колбеков. --- Код скрипта:
Код
--- Функции работы с очередями (написаны на "чистом" Lua без обращения к C-функциям) ---
local new = function ()
return {first = 1 , last = 0 }
end
---
local push = function (self, v)
local last = self.last + 1
self[last] = v
self.last = last
return last
end
---
local pop = function (self)
local first = self.first
if first > self.last then return nil end
local v = self [first]
self.first = first + 1
self[first] = nil
return v, first
end
---
local size = function (self)
return self.last - self.first + 1
end
-----
--------- Создание очереди------
local Queue_QUIK = new()
---------------------------------------
--- Основной поток обработки колбеков "обходит", запушенные на выполнение скрипты, с тем чтобы по событиям запускать их колбеки.
-- При этом должна быть обеспечена корректная синхронизация выполнения байт-кода колбека таким образом, что он не может выполняеться
-- параллельно с байт-кодом потока main.
----------------------
local for_OnParam = 2 -- Множитель количества записей в очередь ----
local N_OnParam = 0
--- OnParam написана на "чистом" Lua без обращения к C-функциям ---
function OnParam(p1, p2)
for i = 1, for_OnParam do
N_OnParam = N_OnParam + 1
-- Зпаись события ---
push (Queue_QUIK, {'OnParam', N_OnParam, {p1, p2}}) -- 1. здесь создаются таблицы и может быть запущена автоматическая сборка мусора,
-- которая работает для всей инсталяции Lua и не является потокобезопасной ---
end
end
---- Обработка событий QUIK (написана на "чистом" Lua без обращения к C-функциям) ----
local function handle_events()
----- #### Для отладки ---
local OnParam_begin = N_OnParam
local size_Queue_QUIK = size(Queue_QUIK)
---------------------------------
--- Чтение очереди событий -----
local ms, first_q = pop (Queue_QUIK)
while ( ms ) do --- Есть события ---
-------------------------------
--- Чтение очереди событий -----
ms, first_q = pop (Queue_QUIK) --Queue_QUIK: pop()
end
---
for i = 1, 1000 do end ---- нагрузка #### Отладка ---
if N_OnParam ~= OnParam_begin then -- Счетчик N_OnParam может иpмениться только в OnParam
-- А это означает, что одновременно (параллельно) работают поток main и основной
-- поток обработки колбеков, что недопустимо.
--- это C-функция, но она вызывается только если N_OnParam ~= OnParam_begin
message ( ' Параллельное выполнение колбека и потока main: N_OnParam - OnParam_begin = ' .. tostring(N_OnParam - OnParam_begin)
.. ' size_Queue_QUIK = ' .. tostring(size_Queue_QUIK) )
end
----
end
--------------------------------------------------------------------------------------------------------------------
--------
IsRun = true
function main()
-------------------
while IsRun do
handle_events() ---- функция чтения событий OnParam ---
sleep(2)
end
------------------
end
function OnStop()
IsRun = false
return 10000
end
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Пользователь
Сообщений: Регистрация: 12.05.2020
30.08.2021 11:03:13
В моем комментарии в п.2 было описано предложение по добавлению интерфейса работы с событиями QUIK. Ниже выложен код модуля реализации этого предложения на «чистом» Qlua, а также шаблон использования этого модуля. В этом шаблоне демонстрируется схема обработки событий фондового рынка и событий таблиц QUIK. Для подключения модуля к шаблону его надо сохранить в файле под именем even_handling_module.lua в папку хранения кода запуска QUIK (info.exe). Код модуля и шаблона можно использовать свободно. При его распространении желательна ссылка на меня. Описание использования модуля приведено в его коде и коде шаблона, описывающего схему обработки событий QUIK. ---- Код модуля:
Код
--[[ TGB ---- Модуль реализации обработки событий QUIK с использованием очередей событий фондового рынка и событий таблиц QUIK ---
Краткая спецификация модуля.
1. Реализуется схема взаимодействия main с колбеками через две потокобезопасные эффективные очереди, одна из которых обслуживает колбеки
фондового рынка, а вторая, колбеки событий таблиц QUIK, созданных скриптером;
2. При работе обработке колбеков есть две функции: <функция подписки на события фондового рынка>
и <функция подписки на события пользовательских таблиц >; в этих функциях скриптер может, в виде списка (в таблице) подписаться на события
в соответствии с существующими именами колбеков; реализация подписки сведена к автоматическому созданию (скрытых) от пользователя
функций колбеков, записывающих свои параметры с добавлением «от кого параметры» в соответствующие очереди;
3. Для работы с очередями по новой схеме есть две функции чтения соответственно очередям;
при чтении очередей в считываемой таблице передаются: <имя события>, <время записи в очередь>, <параметры в том виде, как они описаны, в существующих колбеках>.
При работе по этой схеме, QLua для скриптера становится однопоточным и снимаются многие сложные проблемы.
----
!! Колбеки OnInit и OnStop обрабатываются как обычно.
-------------------------
--]]
---- Функции работы с очередями (выложенные на форуме Старателем) ------
--- При использовании между потоком колбеков и потоком main потокобезопасные
local Queue = {
new = function (self)
return setmetatable({first = 1 , last = 0 }, {__index = self})
end ,
push = function (self, v)
local last = self.last + 1
self[last] = v
self.last = last
return last
end ,
pop = function (self)
local first = self.first
if first > self.last then return nil end
local v = self[first]
self.first = first + 1
self[first] = nil
return v
end ,
size = function (self)
return self.last - self.first + 1
end
}
--------- Создание очередей-----------
local Queue_QUIK = Queue:new()
local Queue_QUIK_tbl = Queue:new()
----- Функции чтения очередей -------
local function Queue_evn_QUIK() return Queue_QUIK: pop() end
local function Queue_evn_QUIK_tbl() return Queue_QUIK_tbl: pop() end
----- Функции запроса текущих размеров очередей -------
local function sizeQueue_evn_QUIK() return Queue_QUIK: size() end
local function sizeQueue_evn_QUIK_tbl() return Queue_QUIK_tbl: size() end
-- Конец Функции работы с очередями ---------------------------------------
local function f_nil () end
--- Переменные событий фондового рынка -------
OnAccountBala nce = f_nil --- изменение позиции по счету
OnAccountPosit ion = f_nil --- изменение позиции по счету
OnAllTr ade = f_nil --- новая обезличенная сделка
OnClea nUp = f_nil --- смена торговой сессии
OnCl ose = f_nil --- закрытие терминала QUIK или выгрузка файла qlua.dll
OnConnec ted = f_nil --- установление связи с сервером QUIK
OnDepoLi mit = f_nil --- изменение бумажного лимита
OnDepoLimitDel ete = f_nil --- удаление бумажного лимита
OnDisconnec ted = f_nil --- отключение от сервера QUIK
OnF irm = f_nil --- получение описания новой фирмы
OnFuturesClientHold ing = f_nil --- изменение позиции по срочному рынку
OnFuturesLimitCha nge = f_nil --- изменение ограничений по срочному рынку
OnFuturesLimitDel ete = f_nil --- удаление лимита по срочному рынку
-- OnI nit = f_nil --- инициализация функции main
OnMoneyLi mit = f_nil --- изменение денежного лимита
OnMoneyLimitDel ete = f_nil --- удаление денежного лимита
OnNegD eal = f_nil --- новая заявка на внебиржевую сделку или изменение параметров существующей заявки на внебиржевую сделку
OnNegTr ade = f_nil --- новая сделка для исполнения или изменение существующей сделки для исполнения
OnOr der = f_nil --- новая заявка или изменение параметров существующей заявки
OnPa ram = f_nil --- изменение текущих параметров
OnQu ote = f_nil --- изменение стакана котировок
-- OnS top = f_nil --- остановка скрипта из диалога управления
OnStopOr der = f_nil --- новая стоп-заявка или изменение параметров существующей стоп-заявки
OnTr ade = f_nil --- новая сделка или изменение параметров существующей сделки
OnTransRe ply = f_nil --- ответ на транзакцию
------
local unsubscribe_tbl = ---- Функции отписки ----
{
['OnAccountBalance'] = function () OnAccountBala nce = f_nil end
, ['OnAccountPosition'] = function () OnAccountPosit ion = f_nil end
, ['OnAllTrade'] = function () OnAllTr ade = f_nil end
, ['OnCleanUp'] = function () OnClea nUp = f_nil end
, ['OnClose'] = function () OnCl ose = f_nil end
, ['OnConnected'] = function () OnConnec ted = f_nil end
, ['OnDepoLimit'] = function () OnDepoLi mit = f_nil end
, ['OnDepoLimitDelete'] = function () OnDepoLimitDel ete = f_nil end
, ['OnDisconnected'] = function () OnDisconnec ted = f_nil end
, ['OnFirm'] = function () OnF irm = f_nil end
, ['OnFuturesClientHolding'] = function () OnFuturesClientHold ing = f_nil end
, ['OnFuturesLimitChange'] = function () OnFuturesLimitCha nge = f_nil end
, ['OnFuturesLimitDelete'] = function () OnFuturesLimitDel ete = f_nil end
-- , ['OnInit'] = function () OnI nit = f_nil end
, ['OnMoneyLimit'] = function () OnMoneyLi mit = f_nil end
, ['OnMoneyLimitDelete'] = function () OnMoneyLimitDel ete = f_nil end
, ['OnNegDeal'] = function () OnNegD eal = f_nil end
, ['OnNegTrade'] = function () OnNegTr ade = f_nil end
, ['OnOrder'] = function () OnOr der = f_nil end
, ['OnParam'] = function () OnPa ram = f_nil end
, ['OnQuote'] = function () OnQu ote = f_nil end
-- , ['OnStop'] = function () OnS top = f_nil end
, ['OnStopOrder'] = function () OnStopOr der = f_nil end
, ['OnTrade'] = function () OnTr ade = f_nil end
, ['OnTransReply'] = function () OnTransRe ply = f_nil end
}
-----
local subscribe_tbl = ---- Функции подписки ----
{
['OnAccountBalance'] = function () OnAccountBala nce = function (...) Queue_QUIK: push ({'OnAccountBalance', os.time (), {...}} ) end end
, ['OnAccountPosition'] = function () OnAccountPosit ion = function (...) Queue_QUIK: push ({'OnAccountPosition', os.time (), {...}} ) end end
, ['OnAllTrade'] = function () OnAllTr ade = function (...) Queue_QUIK: push ({'OnAllTrade', os.time (), {...}} ) end end
, ['OnCleanUp'] = function () OnClea nUp = function (...) Queue_QUIK: push ({'OnCleanUp', os.time (), {...}} ) end end
, ['OnClose'] = function () OnCl ose = function (...) Queue_QUIK: push ({'OnClose', os.time (), {...}} ) end end
, ['OnConnected'] = function () OnConnec ted = function (...) Queue_QUIK: push ({'OnConnected', os.time (), {...}} ) end end
, ['OnDepoLimit'] = function () OnDepoLi mit = function (...) Queue_QUIK: push ({'OnDepoLimit', os.time (), {...}} ) end end
, ['OnDepoLimitDelete'] = function () OnDepoLimitDel ete = function (...) Queue_QUIK: push ({'OnDepoLimitDelete', os.time (), {...}} ) end end
, ['OnDisconnected'] = function () OnDisconnec ted = function (...) Queue_QUIK: push ({'OnDisconnected', os.time (), {...}} ) end end
, ['OnFirm'] = function () OnF irm = function (...) Queue_QUIK: push ({'OnFirm', os.time (), {...}} ) end end
, ['OnFuturesClientHolding'] = function () OnFuturesClientHold ing = function (...) Queue_QUIK: push ({'OnFuturesClientHolding', os.time (), {...}} ) end end
, ['OnFuturesLimitChange'] = function () OnFuturesLimitCha nge = function (...) Queue_QUIK: push ({'OnFuturesLimitChange', os.time (), {...}} ) end end
, ['OnFuturesLimitDelete'] = function () OnFuturesLimitDel ete = function (...) Queue_QUIK: push ({'OnFuturesLimitDelete', os.time (), {...}} ) end end
-- , ['OnInit'] = function () OnI nit = function (...) Queue_QUIK: push ({'OnInit', os.time (), {...}} ) end end
, ['OnMoneyLimit'] = function () OnMoneyLi mit = function (...) Queue_QUIK: push ({'OnMoneyLimit', os.time (), {...}} ) end end
, ['OnMoneyLimitDelete'] = function () OnMoneyLimitDel ete = function (...) Queue_QUIK: push ({'OnMoneyLimitDelete', os.time (), {...}} ) end end
, ['OnNegDeal'] = function () OnNegD eal = function (...) Queue_QUIK: push ({'OnNegDeal', os.time (), {...}} ) end end
, ['OnNegTrade'] = function () OnNegTr ade = function (...) Queue_QUIK: push ({'OnNegTrade', os.time (), {...}} ) end end
, ['OnOrder'] = function () OnOr der = function (...) Queue_QUIK: push ({'OnAccountBalance', os.time (), {...}} ) end end
, ['OnParam'] = function () OnPa ram = function (...) Queue_QUIK: push ({'OnParam', os.time (), {...}} ) end end
, ['OnQuote'] = function () OnQu ote = function (...) Queue_QUIK: push ({'OnQuote', os.time (), {...}} ) end end
-- , ['OnStop'] = function () OnS top = function (...) Queue_QUIK: push ({'OnStop', os.time (), {...}} ) end end
, ['OnStopOrder'] = function () OnStopOr der = function (...) Queue_QUIK: push ({'OnStopOrder', os.time (), {...}} ) end end
, ['OnTrade'] = function () OnTr ade = function (...) Queue_QUIK: push ({'OnTrade', os.time (), {...}} ) end end
, ['OnTransReply'] = function () OnTransRe ply = function (...) Queue_QUIK: push ({'OnTransReply', os.time (), {...}} ) end end
}
-----
-- Подписаться на события фондового рынка --
--- Ключи таблицы - имена событий ----
local function subscribe (tbl)
local err ={}, f
for k, v in next, tbl do
f = subscribe_tbl [k]
if f then f() else err[#err +1] = k end
end
return err
end
-- Отписаться от событий фондового рынка --
--- Ключи таблицы - имена событий ----
local function unsubscribe (tbl)
local err ={}, f
for k, v in next, tbl do
f = unsubscribe_tbl [k]
if f then f() else err[#err +1] = k end
end
return err
end
--- Вывод данных о состоянии подписки на события фондового рынка ---
local function condition_subscribe ()
local tbl= {}
---
tbl['OnAccountBalance'] = OnAccountBalance ~= f_nil or nil
tbl['OnAccountPosition'] = OnAccountPosition ~= f_nil or nil
tbl['OnAllTrade'] = OnAllTrade ~= f_nil or nil
tbl['OnCleanUp'] = OnCleanUp ~= f_nil or nil
tbl['OnClose'] = OnClose ~= f_nil or nil
tbl['OnConnected'] = OnConnected ~= f_nil or nil
tbl['OnDepoLimit'] = OnDepoLimit ~= f_nil or nil
tbl['OnDepoLimitDelete'] = OnDepoLimitDelete ~= f_nil or nil
tbl['OnDisconnected'] = OnDisconnected ~= f_nil or nil
tbl['OnFirm'] = OnFirm ~= f_nil or nil
tbl['OnFuturesClientHolding'] = OnFuturesClientHolding ~= f_nil or nil
tbl['OnFuturesLimitChange'] = OnFuturesLimitChange ~= f_nil or nil
tbl['OnFuturesLimitDelete'] =OnFuturesLimitDelete ~= f_nil or nil
-- tbl['OnInit'] = OnInit ~= f_nil or nil
tbl['OnMoneyLimit'] = OnMoneyLimit ~= f_nil or nil
tbl['OnMoneyLimitDelete'] = OnMoneyLimitDelete ~= f_nil or nil
tbl['OnNegDeal'] = OnNegDeal ~= f_nil or nil
tbl['OnNegTrade'] = OnNegTrade ~= f_nil or nil
tbl['OnOrder'] = OnOrder ~= f_nil or nil
tbl['OnParam'] = OnParam ~= f_nil or nil
tbl['OnQuote'] = OnQuote ~= f_nil or nil
-- tbl['OnStop'] = OnStop ~= f_nil or nil
tbl['OnStopOrder'] = OnStopOrder ~= f_nil or nil
tbl['OnTrade'] = OnTrade ~= f_nil or nil
tbl['OnTransReply'] = OnTransReply ~= f_nil or nil
return tbl
end
----------------------------------------------------------------
---- Обработка событий QUIK ----
----
local tbl_QUIK_fun --- Для хранения функции обработки событий таблиц QUIK ---
local tbl_fun --- Для хранения таблицы функции обработки событий фондового рынка ---
local period = 100 -- период счетчика для выдачи сообшений ---
local event_counter = 0 -- текущее значение циклов "разгребания" очередей событий ---
local event_counter_mess = 0 -- счетчик для выдачи сообщений --
local event_counter_mess = 0 -- счетчик для выдачи сообщений --
local read_latency_max = 0 -- максимальная задержка чтения очередей событий (сек.)--
------------------------------------------------------------------
local tbl_QUIK = {} ---- Общая таблица состояния обработки таблиц QUIK ---
---- Функция обаботки колбеков таблиц QUIK ----
local function callback_tbl_QUIK(...) --- (NUMBER t_id, NUMBER msg, NUMBER par1, NUMBER par2
local par ={...}
par = par[1]
if tbl_QUIK[par] then -- Запись в очередь событий таблиц QUIK. os.time () - дата_время записи ---
Queue_QUIK_tbl: push ({par, os.time (), {...}} )
end
end
-- Подписка на события таблицы QUIK ---
local function subscribe_tbl_QUIK (t_id, f_t)
if tbl_QUIK[t_id] then return nil end
tbl_QUIK_fun = tbl_QUIK_fun or f_t
if SetTableNotificationCallback ( t_id, callback_tbl_QUIK) == 1 then
tbl_QUIK[t_id] = 1
return nil
else
message('!!! Ошибка задания колбека для таблицы: ' .. t_id)
error('!!! Ошибка задания колбека для таблицы: ' .. t_id)
return nil
end
end
-- Отписка от событий таблицы QUIK ----
local function unsubscribe_tbl_QUIK (t_id) -- Отписка от событий таблицы QUIK ---
if tbl_QUIK [t_id] then tbl_QUIK [t_id] = nil end
if next (tbl_QUIK) == nil then tbl_QUIK_fun = nil end
end
-- Состояние подписки на события таблицы QUIK ----
local function condition_subscribe_tbl_QUIK () --- Состояние подписки на события таблиц QUIK ---
return tbl_QUIK
end
-----------------------------------------------
--- Установить функции обработки событий ----
local function install_event_handling_functions(tbl_f)
tbl_fun = tbl_f
event_counter = 0
event_counter_mess = 0
event_counter_max = 0
read_latency_max = 0
--- Подписка на события фондового рынка ---
--- ! Ключи таблицы - имена событий ----
unsubscribe (unsubscribe_tbl) ---- Отписаться от всех событий
subscribe (tbl_f) --- Подписка на события всей таблицы tbl_fun (для записей с функциями обработки событий)
end
---- Функция обработки всех событий QUIK: function handle_events(lim) -----
-- Параметр lim (по умолчанию равен 1000000) определяет максимальное количестко событий, обрабатаваемых за один вызов функции --
--- Если очереди событий пусты, то функция завершается.
-- Результат (их три): 1) количество обработанных событий; 2) максимальное количество событий за один вызов функции;
-- 3) максимальная задержка (в сек.) между записью и чтением событий
local function handle_events(lim)
lim = lim or 1000000
local f_ms
--- Чтение очередей событий -----
local ms_tbl = Queue_QUIK_tbl: pop() -- ms_tbl = {t_id, os.time (), {NUMBER t_id, NUMBER msg, NUMBER par1, NUMBER par2}}
local ms = Queue_QUIK: pop() -- ms_tbl = {<Имя события>, os.time (), {<Параметры события>}}
local os_time, os_time_d
---
while (ms_tbl or ms ) do -- Есть события ---
-------------------------------
os_time = os.time ()
event_counter = event_counter + 1
event_counter_mess = event_counter_mess + 1
if event_counter_mess >= period then
event_counter_mess = 0
message ( '!! Длительный цикл обработки событий: ' .. event_counter )
end
--- Обработка событий таблиц QUIK ---
if ms_tbl then
-- message ( tostring(ms_tbl[1]))
os_time_d = os_time - ms_tbl [2]
if read_latency_max < os_time_d then read_latency_max = os_time_d end
if tbl_QUIK_fun then tbl_QUIK_fun (unpack (ms_tbl[3])) end -- Запуск функции обработки событий таблиц QUIK ---
end
----------- События фондового рынка ---
if type (tbl_fun) == 'table' then
if ms then
os_time_d = os_time - ms [2]
if read_latency_max < os_time_d then read_latency_max = os_time_d end
f_ms = tbl_fun[ms[1]]
-- message ( tostring(ms[3][2]))
if f_ms then f_ms (unpack (ms[3])) end -- Запуск функции обработки событий фондового рынка ---
end
end
if event_counter >= lim then break end
--- Чтение очередей событий -----
ms_tbl = Queue_QUIK_tbl: pop() -- ms_tbl = {t_id, os.time (), {NUMBER t_id, NUMBER msg, NUMBER par1, NUMBER par2}}
ms = Queue_QUIK: pop()
end
--- Ведение счетчиков циклов обработки событий ----
if event_counter_max < event_counter then
event_counter_max = event_counter
end
event_counter_rt = event_counter
event_counter = 0
event_counter_mess = 0
read_latency_max = 0
return event_counter_rt, event_counter_max, read_latency_max
end
-----------------------------------------------
return {
-- Queue = Queue --- Функции работы с очередями ----
-- , Queue_evn_QUIK = Queue_evn_QUIK -- Чтение параметров событий рынка ---
-- , Queue_evn_QUIK_tbl = Queue_evn_QUIK_tbl -- Чтение параметров событий таблиц QUIK ---
sizeQueue_evn_QUIK = sizeQueue_evn_QUIK -- Текущий размер очереди событий рынка ---
, sizeQueue_evn_QUIK_tbl = sizeQueue_evn_QUIK_tbl -- Текущий размер очереди событий таблиц QUIK ---
, subscribe = subscribe -- Подписаться на события фондового рынка --
, unsubscribe = unsubscribe -- Отписаться от событий фондового рынка --
, condition_subscribe = condition_subscribe -- Сотояние подписки на события фондового рынка --
, subscribe_tbl_QUIK = subscribe_tbl_QUIK -- Подписаться на события таблиц QUIK --
, unsubscribe_tbl_QUIK = unsubscribe_tbl_QUIK -- Отписаться от событий таблиц QUIK --
, condition_subscribe_tbl_QUIK = condition_subscribe_tbl_QUIK -- Сотояние подписки на таблицы QUIK --
, install_event_handling_functions = install_event_handling_functions -- Установить функции обработки событий ----
, handle_events = handle_events -- Функция обработки всех событий QUIK -----
} ---
--------------------------------------
---- Код шаблона:
Код
local even_handling_module = require('even_handling_module') -- Подключение модуля обработки событий QUIK ---
---
local subscribe = even_handling_module.subscribe
local unsubscribe = even_handling_module.unsubscribe
local condition_subscribe = even_handling_module.condition_subscribe
local subscribe_tbl_QUIK = even_handling_module.subscribe_tbl_QUIK
local unsubscribe_tbl_QUIK = even_handling_module.unsubscribe_tbl_QUIK
local condition_subscribe_tbl_QUIK = even_handling_module.condition_subscribe_tbl_QUIK
local sizeQueue_evn_QUIK = even_handling_module.sizeQueue_evn_QUIK
local sizeQueue_evn_QUIK_tbl = even_handling_module.sizeQueue_evn_QUIK_tbl
local install_event_handling_functions = even_handling_module.install_event_handling_functions
local handle_events = even_handling_module.handle_events
IsRun = true
function main()
--- Работа с событиями таблиц QUIK -----
----- Функция обработки событий таблиц QUIK -----
-- FUNCTION (NUMBER t_id, NUMBER msg, NUMBER par1, NUMBER par2) ---
-- t_id – идентификатор таблицы; msg – код сообщения; par1 и par2 – значения параметров определяются типом сообщения msg ----
local function tbl_QUIK_fun (t_id, msg, par1, par2)
message ( 'tbl_QUIK_fun (t_id: ' .. t_id)
end
-----
TableQUIK=AllocTable() -- Создание таблицы QUIK --
AddColumn(TableQUIK, 1, "Легенда", true, QTABLE_STRING_TYPE, 6)
AddColumn(TableQUIK, 2, "Год", true, QTABLE_STRING_TYPE, 6)
AddColumn(TableQUIK, 3, "Месяц", true, QTABLE_STRING_TYPE, 6)
AddColumn(TableQUIK, 4, "День", true, QTABLE_STRING_TYPE, 6)
CreateWindow(TableQUIK)
for i=1,10 do -- Цикл заполняет ячейки
InsertRow(TableQUIK,-1)
for j=1,4 do
SetCell(TableQUIK, i, j, tostring(i).."-"..tostring(j))
end
end
TableQUIK1=AllocTable() -- Создание таблицы QUIK --
AddColumn(TableQUIK1, 1, "Легенда", true, QTABLE_STRING_TYPE, 6)
AddColumn(TableQUIK1, 2, "Год", true, QTABLE_STRING_TYPE, 6)
AddColumn(TableQUIK1, 3, "Месяц", true, QTABLE_STRING_TYPE, 6)
AddColumn(TableQUIK1, 4, "День", true, QTABLE_STRING_TYPE, 6)
CreateWindow(TableQUIK1)
for i=1,10 do -- Цикл заполняет ячейки
InsertRow(TableQUIK1,-1)
for j=1,4 do
SetCell(TableQUIK1, i, j, tostring(i).."-"..tostring(j))
end
end
---
subscribe_tbl_QUIK (TableQUIK, tbl_QUIK_fun) --- Подписка на события TableQUIK
subscribe_tbl_QUIK (TableQUIK1, tbl_QUIK_fun) --- Подписка на события TableQUIK1
-- unsubscribe_tbl_QUIK (TableQUIK) --- Отдписка от событий TableQUIK1
--- Конец Работа с событиями таблиц QUIK -----
--- Работа с событиями фондового рынка ----
--- Функции обработки событий фондового рынка ---
local function F_OnParam(p1, p2)
-- message ( 'Тикер: ' .. tostring(p2))
end
--
local function F_OnAllTrade(t)
message ( 'F_OnAllTrade: ' )
end
local function F_OnConnected(t)
message ( 'F_OnConnected: ' )
end
---- и т.д ----
-------------------------------------------------------------------
------ !!! Для перехода на обработку событий в очередях, в скрипте достаточно к именам функций колбеков добавить префикс 'F_'
--- Таблица функций обработки событий фондового рынка (параметры как в соответствующих колбеках) -----
local tbl_fun =
{
['OnAccountBalance'] = F_OnAccountBalance --- Имя функции обработки события OnAccountBalance --
, ['OnAccountPosition'] = F_OnAccountPosition -- и т.д. ---
, ['OnAllTrade'] = F_OnAllTrade
, ['OnCleanUp'] = F_OnCleanUp
, ['OnClose'] = F_OnClose
, ['OnConnected'] = F_OnConnected
, ['OnDepoLimit'] = F_OnDepoLimit
, ['OnDepoLimitDelete'] = F_OnDepoLimitDelete
, ['OnDisconnected'] = F_OnDisconnected
, ['OnFirm'] = F_OnFirm
, ['OnFuturesClientHolding'] = F_OnFuturesClientHolding
, ['OnFuturesLimitChange'] = F_OnFuturesLimitChange
, ['OnFuturesLimitDelete'] = F_OnFuturesLimitDelete
-- , ['OnInit'] = F_OnInit
, ['OnMoneyLimit'] = F_OnMoneyLimit
, ['OnMoneyLimitDelete'] = F_OnMoneyLimitDelete
, ['OnNegDeal'] = F_OnNegDeal
, ['OnNegTrade'] = F_OnNegTrade
, ['OnOrder'] = F_OnOrder
, ['OnParam'] = F_OnParam
, ['OnQuote'] = F_OnQuote
-- , ['OnStop'] = F_OnStop
, ['OnStopOrder'] = F_OnStopOrder
, ['OnTrade'] = F_OnTrade
, ['OnTransReply'] = F_OnTransReply
}
install_event_handling_functions (tbl_fun) -- Установка таблицы функций обработки событий фондового рынка ---
----
for i, v in next, condition_subscribe() do
message( 'Скрипт подписан на событие фондового рынка ' .. i )
end
--- Работа с событиями фондового рынка ----
-------------------
while IsRun do
---- Функция обработки всех событий QUIK: function handle_events(lim) -----
-- Параметр lim (по умолчанию равен 1000000) определяет максимальное количестко событий, обрабатаваемых за один вызов функции --
--- Если очереди событий пусты, то функция завершается.
-- Результат (их три): 1) количество обработанных событий в вызове функции; 2) максимальное количество обработанных событий за один вызов функции;
-- 3) максимальная задержка (в сек.) между записью и чтением событий (в вызове функции).
local event_counter, event_counter_max, read_latency_max = handle_events() ---- Обработка всех событий QUIK ----
if event_counter > 0 then -- В очередях были события ----
message ( 'event_counter: ' .. event_counter .. '; read_latency_max: ' .. read_latency_max )
end
---- Обработка в main остального -----
---- Конец Обработка в main остального -----
sleep(2)
end
------------------
end
function OnStop()
IsRun = false
DestroyTable(TableQUIK)
DestroyTable(TableQUIK1)
return 10000 -- !! По истечении этого интервала времени (в млсек.), данного скрипту на завершение работы, функция main() завершается принудительно.
-- При этом возможна потеря системных ресурсов. ! Если функция не выдает значение, то по умолчанию оно 5000 (5 сек.)
end
Робот как источник пассивного дохода?
Пользователь
Сообщений: Регистрация: 12.05.2020
26.08.2021 11:09:43
Цитата
Pavel написал: на счете будет оставаться 500, всё что заработаю планирую выводить.
Вы знаете долларовых миллиардеров, заработавших свои состояния на внутридневной торговли на бирже? Банки, имеющие ресурсы, позволяющие нанимать совешенно продвинутных аналитиков фондового рынка и айтишников, и имеющие возможность создавать дочерние предприятия, занимающие внутридневной торговлей, предпочитают зарабатывать на комиссиях по обслуживанию такой торговли. Вас это не наводит ни на какие размышления? Если бы кто то мог гарантированно получать прибыль 15% годовых в долларах, мы бы это увидели.
Поиск инструмента по названию
Пользователь
Сообщений: Регистрация: 12.05.2020
25.08.2021 12:49:48
Цитата
Виталий написал: Все заработало как следует - терминал перестал падать.
Вы в какой версии Quik работаете? При выкладывании ошибок надо указывать версию QUIK, в которой эта ошибка возникает.
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
17.08.2021 21:43:24
Цитата
Старатель написал: и код в сообщении #24 в частности.
Ответьте, пожалуйста, есть ли в этом коде вызов стандартных функций? Если есть, то какие и как часто?
Нехватка видеопамяти
Пользователь
Сообщений: Регистрация: 12.05.2020
17.08.2021 15:34:39
Цитата
nikolz написал: пора бы усвоить что халява - она и есть халява.Во-первых, весь квик - это официально бесплатный продукт.
Это вам так брокеры рассказывают, но при этом в ваших комиссиях брокеру незримо сидит некий процент отчисления за QUIK. Так что за QUIK пользователь платит и ARQA материально зависит от пользователей.
Это, конечно, аргумент Особенно с учетом того, что вы мне не начальник.
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
16.08.2021 23:26:11
Цитата
s_mike@rambler.ru написал: TGB, прекратите фантазировать.этот код (усложненный) работает в сотнях (может тысячах, я не знаю) копий роботов, из числа выложенных на сайте и написанных под заказ.
Вы что, никогда не сталкивались с ситуацией, когда программы использовались сотнями тысячами пользователями и в этих программах потом обнаруживались ошибки?
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
16.08.2021 23:13:26
Цитата
s_mike@rambler.ru написал: этот код (усложненный) работает в сотнях (может тысячах, я не знаю) копий роботов, из числа выложенных на сайте и написанных под заказ.
Я же написал, что, похоже, что код потокобезопасный. Но если вам все известно, то объясните, что происходит время от времени в коде Старателя?
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
16.08.2021 22:21:20
Цитата
Старатель написал: код в сообщении #24 в частности.
Выполненные мною в Lua 5.3 (5.4) тесты атомарности операций вставки/удаления полей в таблицу показали, что эти операции (в условиях реализован-ной многопоточности QLua) все-таки атомарны. Возможно?, есть ситуации, не охваченные тестированием, когда атомарности может не быть. Если же таких ситуаций нет, то мое утверждение, что выложенный Старателем код Queue (с описанием редко возникающей ошибки) создает потокоопасные очереди, ошибочное.
TGB написал: TGB написал:10000 обращений (запись, чтение, удаление) за 500 миллисекунд.Не смотря на то, что сам тест бестолковый, но холостой цикл за 0,5 сек не слишком ли много?
Опять неточность (мы же обсуждаем код Queue_safe). В моем обсуждаемом коде Queue_safe во фрагменте тестирования указано: -- 1. Этот фрагмент (использование потокобезопасных функций QLua) (100 000 записей и чтений) выполняется за ~3560 милисекунд --- ................ -- 2. Этот фрагмент (использование Queue_safe) (100 000 записей и чтений) выполняется за ~55 милисекунд ---
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
16.08.2021 17:41:44
Цитата
Старатель написал: И не увидел в вашем комментарии каких-то существенных отличий касательно использования метода pop().Больше похоже на спам вашего OS_...
Вы в комментарии читали это: 2. Существенная особенность построения очередей в OS_Quesha состоит в том, что они строятся на таблицах, в которых после их создания, нет вставок или удалений их полей (записей). В процессе работы с очередями изменяются только значения существующих полей, обеспечивающих запись/чтения этих очередей. Структура таблиц очередей «заморожена». Это обеспечивает в многопоточном режиме возможность эффективной синхронизации работы с очередями на уровне их полей, а не на глобальном уровне самих очередей. Так вот, эта существенная особенность обеспечивает то, что приведенный в комментарии конкретный код модуля Queue_safe создания очередей между колбеками и main является потокобезопасным в существующем QLua, в отличие от выложенного вами Queue, который потокобезопасным не является, о чем я уже писал в этой ветке.
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
15.08.2021 16:04:35
Цитата
Старатель написал: local hour = 0+os.date('%H') выскочила такая ошибка: attempt to perform arithmetic on a nil value
Ошибка, которую вы обнаружили, замечательна своей локализацией (всего одна строка кода). --- Я посмотрел в исходниках Lua 5.3 код функции os.date и то, как она вызывается на исполнение в коде Lua. Этот код не блокирует потоки в текущей версии QLua 5.3 (и это легко проверить). При этом, os.date, формально, не является C-функцией, так как в внутри ее кода, без блокировки, используется среда исполнения Lua (ее внутренние функции), формально не гарантирующая корректного параллелизма при ее использовании. Это же относится к некоторым другим библиотечным функциям Lua, имеющим признак C-функций. В C-функциях можно использовать только C-API Lua. Использование внутренних функции Lua, без блокировки, в коде C-функций является ошибкой. В версии Lua 5.3 (а возможно и в 5.4), похоже, есть «дыра» в некоторых ее стандартных функциях, для работы с ними из разных потоков. При работе в однопоточном варианте Lua такая «дыра» проявить себя не может. Но, собственно, разработчики Lua не один раз заявляли, что поддерживают однопоточный вариант Lua, а остальное факультатив, с которым надо разбираться тем, кто встраивает Lua в свои решения. ------ Конечно, можно попытаться анализировать все коды стандартных функций с используемыми внутренними функциями Lua без блокировки («раскручивая» соответствующие цепочки вызовов внутренних функций Lua) с целью выяснения, вдруг, случайно, какие то, из них, корректны при работе в нескольких потоках. Но по-хорошему, при написании всех кодов модулей библиотечных функции Lua, из ее среды исполнения, должно быть доступно только ее API (обеспечивающее корректность обращения к Lua из разных потоков). В принципе, для разработчика QUIK есть простой вариант исправления, в исходниках QLua, стандартных функций с используемыми внутренними функциями Lua без блокировки: в начале кода таких функций выполняется lua_lock, а при выходах из них (! их может быть несколько) выполняется lua_unlock.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Пользователь
Сообщений: Регистрация: 12.05.2020
14.08.2021 19:36:06
Цитата
Владимир написал: Мне нет никакого дела до "проблем параллелизма в QLua" - мой скрипт считает, что он один такой работает, и про потоки и прочее знать ничего не знает - для него есть только прерывания от таймера, клавы или мыши.
Думать вы так, конечно, можете, а что же вы иногда жалуетесь на непонятные "падения" вашего скрипта? А может быть и кто то еще получает непонятные ситуации? Как системщик вы, наверное, должны понимать, что вам (нам) не обеспечена более-менее надежная среда разработки и исполнения скриптов. Вы что против того, чтобы надежность QLua повышалась? Если нет, то разработчик QUIK должен разбираться, с потоками, синхронизацией и т.д., часто, скрытыми API QUIK, но влияющими работу скриптов. И почему бы, если у кого есть такая возможность, не посодействовать ему, в этом, для нашей пользы?
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Пользователь
Сообщений: Регистрация: 12.05.2020
14.08.2021 17:26:34
Цитата
Владимир написал: вся задача организации торговли прикладная с головы до пят, и любые попытки привнести сюда системные штучки-дрючки - тем более, глубоко системные, как в данном случае, ни к чему хорошему не приведут.
Очень филосовское замечание Где вы видите системные штучки? Код написан на чистом Lua (даже циклов нет ). --- Я не понял ваших замечаний. Что в коде не так? Здесь выложен конкретный код, который, возможно, пригодится для устранения ситуации, описанной в комментарии: или для варианта модификации QLua, описанного в п.2 комментария: и освобождающего скриптера от проблем параллелизма в QLua, Этот код может оказаться интересным и еще кому-нибудь. При описании кода я коротко отметил его существенную особенность, Для кого-то из читателей будет понятно, почему это сделано так. Что в этом плохого? Вы же можете пользоваться своими "безразмерными" прикладными очередями или, например, использовать безразмерную (очень простую) очередь, код которой приведен в описании упомянутой мною ситуации. Но скорее всего, вам не нужны никакие очереди. Ну и замечательно.
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
14.08.2021 11:28:30
Цитата
Старатель написал: это уже вне зоны ответственности скриптера, а ошибка в реализации многопоточной модели QLUA.
1. Для устранения вашей конкретной ситуации, возможно, подойдет вариант реализации очередей, приведенный в моем комментарии 2. Вообще, существует сравнительно несложный вариант заметно улучшить QLua (сделав его однопоточным для скриптера) без изменения его внутренней архитектуры: 1) добавить в API QLua функцию <задание схемы обработки колбеков>, которую скриптер может (но не обязательно) вызвать в начале своего скрипта с параметром задания схемы; если эта функция не вызвана, то колбеки обрабатывыются так, как это делается сейчас по старой схеме; дополнительно, в этой функции можно бы задавать версию Lua, а возможно и еще что-нибудь; при задании новой схемы, внутри QLua автоматически реализуется схема взаимодействия main с колбеками через две потокобезопасные эффективные очереди (как обеспечить их эффективность, наверное, понятно), одна из которых обслуживает колбеки фондового рынка, а вторая, колбеки событий таблиц QUIK, созданных скриптером; 2) при работе по новой схеме обработки колбеков, в API QLua добавить еще две функции: <функция подписки на события фондового рынка> и <функция подписки на события пользовательских таблиц >; в этих функциях скриптер может, в виде списка (в таблице) подписаться на события в соответствии с существующими именами колбеков; реализация подписки разработчиком QUIK может быть сведена к автоматическому созданию (скрытых) от пользователя функций колбеков, вызываемых, как это делается сейчас, и записывающих свои параметры с добавлением «от кого параметры» в соответствующие очереди; 3) для работы с очередями по новой схеме в API QLua добавить две функции чтения (?возможно также и выполнения некоторых дополнительных функций), соответственно очередям; при чтении очередей в считываемой таблице передаются: <имя события>, <время записи в очередь>, <параметры в том виде, как они описаны, в существующих колбеках>. При работе по второй схеме, QLua для скриптера становится однопоточным и снимаются многие сложные проблемы. Причем, остается возможность не затрагивать и тех скриптеров, которые по тем или иным причинам не станут уходить от старой схемы. ---- Общая схема работы скриптера в новой схеме обработки событий QUIK. <Заказывается новая схема обработки событий > <Выполняется подписка (вместо написания функций колбеков) на обрабатываемые события QUIK> <В функции main, в цикле читаются две очереди и обрабатываются считанные параметры событий> ------- Мною была описан некий, как мне представляется, не сильно сложный вариант реализации избавления QLua от проблем параллелизма, связанных с его существующей реализацией.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Пользователь
Сообщений: Регистрация: 12.05.2020
14.08.2021 09:18:24
Реализация очередей в OS_Quesha. 1. Кроме ранее описанного контроля, в системе выполняется периодический контроль текущих размеров всех ее очередей. При создании каждой очереди задается ее предельно-допустимый размер. Если текущий размер, какой то очереди превышает 75% предельно-допустимого, в системе начинает выдаваться об этом сообщение. 2. Существенная особенность построения очередей в OS_Quesha состоит в том, что они строятся на таблицах, в которых после их создания, нет вставок или удалений их полей (записей). В процессе работы с очередями изменяются только значения существующих полей, обеспечивающих запись/чтения этих очередей. Структура таблиц очередей «заморожена». Это обеспечивает в многопоточном режиме возможность эффективной синхронизации работы с очередями на уровне их полей, а не на глобальном уровне самих очередей. Далее выложен работающий код реализации очередей с учетом выше написанного для частного случая, когда один поток в нее пишет, а другой читает (!не допустимы чтения или записи в нескольких потоках):
Код
---- Реализация циклических потокобезопасных очередей без синхронизации для случая, когда один поток в нее пишет, а другой читает (!не допустимы чтения или записи в нескольких потоках)------
local Queue_safe = {
--- size_Queue - размер очереди ----
new = function (self, size_Queue)
local Queue = {}
local cycl = {} -- таблица-массив хранения элементов очереди
for i =1, size_Queue do
cycl[i] = 0
end
Queue.cycl = cycl
Queue.QueueLength = size_Queue --- размер очереди ---
Queue.RecordPointer = 1 --- указатель записи (изменяется только "писателем") ---
Queue.ReadingPointer = 1 --- указатель чтения (изменяется только "читателем") ---
Queue.written_down = 0 --- количество записанных элементов ---
Queue.read = 0 --- количество считанных элементов ---
return setmetatable(Queue, {__index = self}) --- для переключения на Queue_safe при обращение в созданной таблице к push, pop, size ----
end,
--- Записываемое в очередь значение не может быть nil --
-- Результат: 0 - запись выполнена; 1 - запись не выполнена (нет места)
push = function (self, v)
if v == nil then error(' !!! В очередь нельзя записывать nil ') end
if self.written_down - self.read >= self.QueueLength then ----- некуда писать ----
return (1)
end
local cycl = self.cycl
local pwt= self.RecordPointer
cycl [pwt] = v
local pwf = pwt +1
if pwf > self.QueueLength then
pwf=1
end
self.RecordPointer = pwf --- следующая позиция для записи (возможно занятая) --
self.written_down = self.written_down + 1
return (0)
end,
--- Два результата: 1) элемент или nil; 2) признак: 0 - очередь после чтения пуста; > 0 - количество непрочитанных элементов; -1 - очередь пуста в момент чтения;
pop = function (self)
local n = self.written_down - self.read
if n == 0 then
return nil, -1 --- нет данных
end
local cycl = self.cycl
local prt= self.ReadingPointer
local v = cycl [prt]
cycl [prt] = 0 --- чтобы не было "висячих" ссылок на ссылочные объекты ----
prt = prt +1
if prt > self.QueueLength then
prt = 1
end
self.ReadingPointer = prt
self.read = self.read + 1
return v, n - 1
end,
size = function (self)
return self.written_down - self.read
end
}
----------------------------------------------------------------------
------ Тесты -----
local T
local v
--[[
-- 1. Этот фрагмент (использование потокобезопасных функций QLua) (100 000 записей и чтений) выполняется за ~3560 милисекунд ---
T = {}
for j = 1, 100 do
for i = 1, 1000 do --- запись в очередь
table.sinsert (T, 'sd')
end
for i = 1, 1000 do --- чтение из очереди
v = T[1]
table.sremove (T, 1)
end
end
do return end ------
-----------------------------------------------------------------
--]]
-- 2. Этот фрагмент (использование Queue_safe) (100 000 записей и чтений) выполняется за ~55 милисекунд ---
T = Queue_safe:new(1200)
for j = 1, 100 do
for i = 1, 1000 do --- запись в очередь
T: push('sd')
end
for i = 1, 1000 do --- чтение из очереди
v = T: pop()
end
end
--------------------------------------------------------------
Относительно выложенного кода можно отметить следующее. 1. Это сильно упрощенный, работающий вариант реализации очередей, которые используются в OS_Quesha. 2. Особенностью этих очередей, при их создании, является необходимость задания их предельного размера. При записи в очередь, выдается признак успешности этой записи, либо отсутствия места в очереди. 3. Работа с создаваемыми очередями потокобезопасна без синхронизации при их использовании в QLua между колбеками и main. 4. Скорость выполнения операций запись/чтение не зависит от текущей длины очередей (в отличие от очередей, реализуемых с помощью table.sinsert и table.sremove, в которых скорость операций с увеличением текущей длины очереди, резко падает).
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
12.08.2021 16:35:38
Цитата
Старатель написал: Абсолютно беспочвенное утверждение, говорящее об отсутствии понимания работы обсуждаемого кода.
Вы имеете ввиду, что для записи и чтения в очередь используются свои указатели и, я бы с вами согласился, если бы не существовал общий объект, в котором это происходит (таблица хранения очереди в которую вставляются и из которой вычеркиваются элементы очереди). Вы уверены, что работа с таблицей при изменении ее структуры в Lua реализована потокобезопасно? Где это написано?
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
12.08.2021 15:22:34
Цитата
Старатель написал: В качестве разминки сделайте перезаказ обезличенных сделок (или переключитесь на другой сервер) ближе к концу торговой сессии и посмотрите, с какой задержкой будет обрабатываться ваша очередь и расход памяти скриптом.
Очередь не моя, а разработчика QUIK. Мне не известно как вы обрабатываете обезличенные сделки (сколько это может занимать ресурсов ПК), поэтому я запустил тест для проверки времени выполнения потокобезопасных функций реализации только очереди:
Код
---- Скрипт -тест ----
-- Этот фрагмент выполняется ~500 милисекунд ---
local T = {}
local v
for j = 1, 10 do
for i = 1, 1000 do --- запись в очередь
table.sinsert (T, {'sdfdfmffmf', 57})
-- v = T[1]
-- table.sremove(T, 1)
end
for i = 1, 1000 do --- чтение из очереди
-- table.sinsert (T, {'sdfdfmffmf', 57})
v = T[1]
table.sremove(T, 1)
end
end
10000 обращений (запись, чтение, удаление) за 500 миллисекунд. Понятно, что тест искуственный (без взаимодействия с колбеками), но какое то представление о скорости работы очереди и допустимой ее длине он дает. Заметного роста памяти QLua я не заметил.
Цитата
Старатель написал: Цитата TGB написал: В вашем коде, по вашей ссылке, используется в двух потоках потоконебезопасная очередь OnAllTrades. И?
Это значит, что при работе с такой очередью могут возникать ошибки синхронизации, которые могут порождать наблюдаемые вами последствия.
==========================
Цитата
_sk_ написал: Очередь, реализованная Старателем, в этом случае корректно работает и без блокировок.
А что же ситуации время от времени возникают?
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
12.08.2021 12:48:58
Цитата
Старатель написал: Старатель написал: local hour = 0+os.date('%H') выскочила такая ошибка: attempt to perform arithmetic on a nil value
Меня заинтриговала ошибка, которую вы обнаружили, в таком коротком коде. Напишите, пожалуйста: Как часто выполняется в скрипте приведенный вами фрагмент? Где это выполняется: в main или колбеках? -----------------------
Цитата
Старатель написал: Также ошибка attempt to call a nil value (method 'pop') в 9.1 никуда не пропала. Откуда здесь nil?
В вашем коде, по вашей ссылке, используется в двух потоках потоконебезопасная очередь OnAllTrades. В API QLua есть функции реализации потокобезопасной очереди, созданные разработчиком QUIK: table.sinsert, table.sremove. Пример использования потокобезопасной очереди:
Работа функций OnStop() и SetCell(), Подвисает скрипт
Пользователь
Сообщений: Регистрация: 12.05.2020
09.08.2021 21:51:20
Цитата
Roman Azarov написал: Просьба уточнить, о каких конкретно функциях, вызываемых из OnStop(), идет речь?
Цитата (не точная) из известной юморески: "Принесите справки от всех женщин, что вы на них не женаты."
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
09.08.2021 18:24:01
Об атомарности операций. Рассуждения об атомарности операции без определения ее области реализации это рассуждение о погоде без определения, к чему это относится (к Арктике или Антарктиде). Все операции скрипта, по отдельности, команды байт-кода или вызов C-функций являются атомарными, но в тоже время, выполнение скрипта, в целом, может быть и не атомарным (потоконебезопасным). Это связано с тем, что между упомянутыми операциями могут возникнуть переключение потоков, изменяющее контекст выполнение локально-атомарных операций. На самом деле, для выяснения потокобезопасности (атомарности выполнения скрипта в целом) достаточно выявить общие данные, модифицируемые в main и в основном служебном потоке QUIK, генерирующем вызовы колбеков скрипта. Если таких данных нет (а это часто можно обеспечить), то бессмысленно гадать об атомарности отдельных операций скрипта (скрипт выполняется атомарно, то есть, потокобезопасно, если нет таких данных).
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Пользователь
Сообщений: Регистрация: 12.05.2020
09.08.2021 12:23:37
Дополнительно к тому, что было написано в моих предыдущих комментариях относительно OS_Quesha. 1. То, что написано в них, не относится к начальному «освоению» QLua. Это может оказаться интересным, наверное, тем, кто в этом «поварится» некоторое время, после которого проявятся те проблемы, о которых я пишу. 2. Моя позиция относительно любых средств разработки программ: они должны облегчать жизнь пользователя таких средств. Если есть возможность обеспечить такое, то пользователя надо, освобождать от сложных проблем параллельного программирования или обеспечения надежности разрабатываемых программ. 3. OS_Quesha, обеспечивая многопоточность скрипта, написанного на QLua, полностью (если не используются общие модифицируемые в нескольких потоках данные, для работы с которыми есть средства для «продвинутых» разработчиков) освобождают разработчика таких скриптов от проблем параллельного программирования и обеспечивает их надежность. 4. В продолжение моего комментария, в котором описаны средства обеспечения надежности скриптов QLua с использованием контрольных точек. Известными проблемами любых программ являются: 1) их возможные блокировки при обращении к разделяемым ресурсам (с синхронизацией доступа к ним); 2) их возможные зацикливания (из-за ошибок в них); 3) «утечка» памяти (из-за ошибок в них). Не существует универсальных, автоматических решений этих проблем. Уже хорошим решением может быть: ранняя диагностика таких проблем и это обеспечивается в OS_Quesha. В OS_Quesha выполняется контроль: 1) блокировок ее потоков; 2) зацикливания ее потоков; 3) утечки памяти QLua; 4) утечки памяти самого QUIK. Так как нормальные автоматические обработки описанных выше ситуаций мне не известны (они, как правило, связаны с существенными ошибками в скрипте, или QUIK), то по ним выдается четкая диагностика, а далее есть два варианта: продолжение работы скрипта (с продолжением выдачи упомянутой диагностики) или его перезапуск (возможно с перезапуском QUIK). В обобщенной классификации, OS_Quesha является «форком QLua», и в нем нет тех проблем, которые описаны в моем комментарии, относительно QLua, в соседней ветке «Отладка QUIK 8.13»;
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
06.08.2021 12:40:31
В предыдущих комментариях, при обсуждении конкретного, протестированого в непрерывном недельном прогоне, решения (в виде мизерной правки в 4-х местах исходников QLua), исправляющего, по моему мнению, существующую в QLua ошибку, было написано много текста, в котором можно «сломать голову».
На самом деле все достаточно просто. В QUIK запускается единственный служебный «основной» поток, который об-служивает колбеки всех запущенных скриптов пользователя и его созданных таблиц QUIK. В текущий момент существует, по крайней мере, два варианта, когда скриптер может, «случайно», выполнением кода своего скрипта, заблокировать «основной» поток (при этом перестают запускаться колбеки всех запущенных в QUIK пользователем скриптов и все скрипты «слепнут»: 1) скриптер написал непосредственно в запуске какого-то своего колбека длительно выполняющуюся функцию (почему бы нет?); 2) скриптер сумел написать в main длительно выполняющийся фрагмент байт-кода, в котором нет вызовов C-функций (почему бы нет?). Первый вариант лечится, если следовать рекомендациям разработчика QUIK по обработке колбеков. При этом, все что делается в main пользователя, становится однопоточным (относительно «основного» потока). «Основной» поток, при обработке колбеков, выполняет только короткие записи параметров колбекков в очереди. Причем, в этом случае, при написании и редактировании скрипта, заниматься синхронизацией с «основным» потоком не надо вообще. Второй вариант скриптер сейчас может лечить каждый раз, при редактировании скрипта, анализируя его текст на наличие фрагментов «длинных» байт-кодов и вставляя в них, в «?? нужных» местах какую-нибудь, функционально пустую C-функцию. Нужно ли это скриптеру, если это можно вылечить, внеся, предложенные мною, исправления в QLua? Могу ли быть ошибки, в предложенном мною? В любом коде ошибки могут быть, но это уже как-то протестировано (непрерывно в течении недель) да и разработчик QUIK может это потестировать.
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
03.08.2021 19:33:54
Цитата
Anton написал: Потому что арка не знает, как устроен луа.
Могут узнать, так как есть исходники Lua и это полное описание Lua (вы, что это не понимаете?).
Знаю. Так как есть исходники Lua. И вы можете узнать, никто не запрещает.
Цитата
Anton написал: Если бы вы это предложение выкатили команде луа, еще куда б ни шло, там хоть последствия понимают.
Команде Lua это не нужно. Как только вы встраиваете Lua в свою систему, за последствия отвечаете вы (почитайте в тексте исходников Lua комментарии; они же в свободном доступе).
Цитата
Anton написал: Еще раз, в текущем луа есть удобная особенность атомарности исполнения байткода. Вы это хотите сломать. Я против самой идеи это ломать.
Конечно, при этом исчезает интересная возможность многочасового гадания в коде скрипта на атомарность/неатомарность , если не следовать рекомендациям разработчика QUIK по взаимодействию с колбеками. Но самое интересное, даже, если вы убежденный противник рекомендаций разработчика Quik и не используете потокобезопасную очередь между вызовом колбеков и main, то, если нет общих данных, модифицируемых в вызовах колбеков и в функциях вызываемых в main, то гаданием атомарность/неатомарность можно, вообще, не заниматься.
Цитата
Anton написал: Как ее решить без ковыряния в кишках луа, я предложил.
Где ваш протестированный вами код?
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
03.08.2021 15:44:23
Цитата
Владимир написал: TGB , Дык я же давал чуть не десяток предложений в одном флаконе, и чуть ли не все они были зарегистрированы.
Вы за то, чтобы поток генерации колбеков блокировался фрагментами байт-кода? У вас есть конкретные замечания и возражения против моего конкретного протестированного предложения по устранению этих блокировок? Вы за то. чтобы был реализовано гипотетическое, "лабударно-завиральное", никак не проверенное предложение Anton, выдвинутое, как мне, но возможно ошибочно, кажется только для дискредитации того, что уже протестировано?
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
03.08.2021 12:01:19
Опять цитата не моя, а Владимира, Извиняюсь перед собой
Я тоже свою систему почти не помню. Но вы же? в свое время? "нахлебались", по "полной", на таблицах QUIK (или нет). Вы что, хотите, чтобы и остальные пользователи получили "свое"? То, что вы просите, можно сделать самому. Вы, ведь, системный программист? Мне, просто бывает интересно (когда есть время), как "кипит" "социальный бульон" в текущее время.
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
03.08.2021 09:18:52
swerg, извиняюсь. В моем предыдущем комментарии все цитата от Anton.
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
03.08.2021 08:52:33
Anton , зачем вы все время требуете продолжение «марлезонского балета»? Ну хорошо, продолжим.
Цитата
Anton написал: Я писал сначала, что не надо луа патчить для решения вашей проблемы?
На самом деле это проблема не моя. Для себя эту проблему я решил достаточно давно (аж в 2019г., когда разработал свою систему создания торговых роботов в QUIK). Утомлять вас здесь тем, как это у меня решено, я не буду.
Цитата
swerg написал: Я написал, как решить ее без патча луа? Написал. Еще что-нибудь?
Ну, наверное, вам бы стоило протестировать (на интервале, хотя бы, трех суток) предложенное вами решение у себя. И изложить его здесь с той же детальностью, как это сделал я. Наверное, из двух работающих решений можно бы выбрать то, которое лучше. Возможно, я бы и сам отказался от своего предложения. Я же не «упертый» и с дельными замечаниями, сделанными мне, легко соглашаюсь (можете посмотреть некоторые мои комментарии). А, кстати, почему вы так упорно боретесь против «форка lua»? Как то это сильно смахивает на борьбу за невинность девушки, которая уже больше года замужем.
Цитата
Anton написал: Нагуглить для вас критическую секцию с таймаутом или сами сумеете?
Этого делать не надо, а лучше поищите закладки в моем коде .
Я в начале 2021г. как-то сравнивал количество внешних функций Qlua и Lua. В Qlua их почти на сотню больше.
Каталог luac-скрипта, выполняемого через dofile
Пользователь
Сообщений: Регистрация: 12.05.2020
02.08.2021 17:11:51
В Lua 5.4 у меня работает это. Внутри откомпилированного скрипта, в начале: <code> -- Функция --- local function dofile_exe_path() local str for i = 2, 4 do --- поиск корневой функции, вызывающей script_path, начиная с функции в которой вызвана script_path -- message (tostring( debug.getinfo(i) )) if debug.getinfo(i) then ---- str = debug.getinfo(i, 'S').source else break end end return str end
local path_script path_script = dofile_exe_path () message( path_script ) -- Результат message строка вида : dofile('<Путь к оттранслированному скрипту>')
<code> Далее, наверное, разберетесь сами.
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
01.08.2021 22:06:19
Я уже думал, что наш диалог завершен, но вы пишите такие фантазийные, детективные тексты, что мне стало интересно.
Цитата
Anton написал: но тем, кто будет писать не как я, подложу-ка я закладочку и выкручивайтесь как выйдет". Вот так вот получается.
Где я такое написал? Если вам кажется, что это находится в опубликованном мною коде, то укажите, где вы нашли такую закладку?
Цитата
Anton написал: Я хорошо понимаю, чего вы добиться хотите
Вы что, экстрасенс ? Я же просто представил протестированный на своем стенде (на котором в сое время тестировал исправление ошибки синхронизации QLua) код исправления блокировок потоков длинными участками байт-кода. Это короткие правки в 4-х местах кода QLua. Их можно изучать визуально, проверять экспериментально, искать в них "до посинения" закладки.
Вот и замечательно! Хорошо построенная программная система должна быть защищенной.
Цитата
Anton написал: В то же время у нас есть виртуальная машина, поэтому арка может добавить отслеживание зависших скриптов, если вместо кондовой CRITICAL_SECTION в качестве лока будет использовать нечто иное с возможностью таймаута на вход. Если таймаут истек и секция не захвачена, весь скрипт убивается как в случае ошибки, все дела. В идеале сначала дергается некий юзерский колбек с вопросом "тебя прибить или сам отвиснешь", если ответил отвисну и не отвис, в морг. Вот что вам стоило бы попросить у арки, а не луа ломать.
И это предлагается вместо "прозрачных" правок в 4-х места кода, вносимых туда в течении пяти минут? Как-то очень сложно (я бы до такого не додумался ) и вот уж куда удобнее вставлять закладки.
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
01.08.2021 19:54:59
Цитата
Anton написал: теперь оказывается надо писать только так и никак иначе
Если вы это так поняли, то, придется, все-таки стоит пояснить. Конечно же, каждый разработчик может писать скрипты как хочет: 1) постоянно, после очередной редакции скрипта, анализируя код на его атомарность/неатомарность (марлезонский балет); 2) не заморачиваясь проблемама синхронизации с колбеками (вообще не зная что такое атомарность) И это никак не связано с тем, останется ли блокировка потоков участками байт-кода (как это про-исходит сейчас) или это будет устранено.
Anton написал: А на других примерах - произойдет. Это типичнейший паттерн вообще-то, как тут можно НЕ увидеть проблем...
Похоже, примеры с вами можно бы было обсуждать бесконечно ----
Цитата
Anton написал: Об чем и речь, весь код У ВСЕХ будет в этих костылях просто потому, что вам кровь из носу хотелось чонить в квике починить, пусть даже и не сломанное.
Опять декларации и страшилки. Но это же можно бы было сформулировать короче: «Не тронь!» Вы что, это не читали?:
Цитата
TGB написал: дело обстоит еще проще. Если вы знакомы с документом разработчика QUIK «Использование Lua в Рабочем месте QUIK.pdf», то его в разделе «2. Взаимодействие потоков Lua скрипта» описана рекомендуемая схема обработки колбеков фондового рынка, которую можно распространить и на обработку колбеков событий таблиц QUIK. Если придерживаться этой схемы, то проблем многопоточности (! из-за основного потока обработки колбеков) в скрипте пользователя не будет вообще: ни в «чистом» Lua-коде ни в смешанном. И не надо ни чем извращаться ни в одной строчке скрипта так как при этом он становится однопоточным (относительно основного потока обработки колбеков). Вы можете почитать комментарии, начиная с , в которых это обсуждается с демонстрацией кодов, рекомендуемых разработчикам QUIK. Если же в скрипте не используется схема обработки колбеков, рекомендованная разработчиком QUIK, то преобразование любого такого скрипта в функционально эквивалентный, но с рекомендованной схемой, элементарное.
или вы убежденный противник решения разработчика QUIK, приведенного в указанном фрагменте текста? Попытаюсь сформулировать, то, что написано там более понятно и короче. Если использовать то, что написано в этом фрагменте, то никакой синхронизации с потоком, обрабатывающем колбеки не требуется. Ни нужны никакие костыли. Не требуется многочасовой анализ кода скрипта на атомарность/неатомарность, (ворк/неворк ). Причем, это справедливо как для существующих версий QLua, так и в случае реализации предлагаемого мною решения, устраняющего ошибку блокировки потоков длинными участками байт-кода. Сформулировать это еще короче я уже, наверное, не смогу
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
01.08.2021 00:39:37
Цитата
Anton написал: Модельку такую можно сделать, а как в реальной жизни к такому коду можно прийти, я прошу продемонстрировать.
Пусть это и демонстрирует реальная жизнь
Цитата
Anton написал: Видите? Я табличку атомарно спрятал в локальную переменную и спокойно удалил. Когда DestroyTable снимает лок, мейн видит вместо таблички нил и все правильно понимает.
Точно также, если переключение (! оно не может возникать внутри команд Lua-машины, а только между ними) в байт-коде вдруг возникнет после tid = nil, но до DestroyTable, то оно снимает лок, мейн видит вместо таблички нил и все правильно понимает. При этом исполнение кода в мейн не сможет блокировать поток обработки колбеков и DestroyTable тоже успешно выполнится. В чем вы видите проблемы?
Цитата
Anton написал: После вашего улучшения такое без критической секции не сделаешь, а их в луа нет, если помните. Придется ради вот этой фигни извращаться. И так на каждой строчке.
Я помню, что в Qlua есть потокобезопасные функции, обеспечивающие функциональность критической секции и нет проблем использовать их в представленном вами примере (вы с этим сами можете разобраться и я не буду тратить время на то, как это можно сделать), Я только не очень понимаю зачем это может потребоваться в приведенном вами примере? Но дело обстоит еще проще. Если вы знакомы с документом разработчика QUIK «Использование Lua в Рабочем месте QUIK.pdf», то его в разделе «2. Взаимодействие потоков Lua скрипта» описана рекомендуемая схема обработки колбеков фондового рынка, которую можно распространить и на обработку колбеков событий таблиц QUIK. Если придерживаться этой схемы, то проблем многопоточности (! из-за основного потока обработки колбеков) в скрипте пользователя не будет вообще: ни в «чистом» Lua-коде ни в смешанном. И не надо ни чем извращаться ни в одной строчке скрипта так как при этом он становится однопоточным (относительно основного потока обработки колбеков). Вы можете почитать комментарии, начиная с , в которых это обсуждается с демонстрацией кодов, рекомендуемых разработчикам QUIK. Если же в скрипте не используется схема обработки колбеков, рекомендованная разработчиком QUIK, то преобразование любого такого скрипта в функционально эквивалентный, но с рекомендованной схемой, элементарное.
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
31.07.2021 20:16:41
Цитата
Anton написал: Было уже написано в этой самой теме не мной. И другие подобные сценарии. Многие вещи, которые в 5.1 требовали длл и никак иначе, теперь можно сделать в скрипте. Вы это хотите сломать. Это уже достаточный аргумент, чтобы не поддержать идею. Можно и в обратную сторону спросить - а что это всем даст? Как скриптер от этого выиграет? Или хотя бы пример делающего что-то полезное кода без сишных вызовов, который иначе ну никак нельзя написать.
Все, что вы написали (включая ссылку) как-то декларативно и нет конкретики. Типа, это не надо делать, потому что не надо. Но в вашем комментарии есть фразы, на которые я попытаюсь ответить или задать вопросы. 1. Каким образом что-то будет ломаться, если будут переключение потоков внутри «чистого» кода Lua (байт-кода)? --- Сейчас переключение потоков в QLua возможно, и выполняется при вызове в скрипте C-функций, которых в рабочем скрипте обычно достаточно много (начиная со sleep). И при этом ничего не ломается. Что изменится в описанном выше качественно, если будут переключения на участках байт-кода? Ничего! Вы же можете, без проблем, в существующий скрипт добавить, для своих целей, новые вызовы C-функций внутрь существующего байт-кода и это нормально. Предлагаемый мною вариант переключения внутри байт-кода это, по сути, добавление очень эффективного вызова «пустой», ничего не делающей C-функции через определенный интервал выполнения команд байт-кода. Это обеспечивает возможность переключения потоков внутри байт-кода и устранение блокировки потоков длительными фрагментами байт-кода. Интервал вызова «пустой» C-функции может быть таким (например, 1000), что дополнительные «окна» переключения потоков практически никак не влияют на скорость выполнения скрипта (это проверено мною экспериментально). При этом разработчику скрипта. дополнительно к тому, чем занимается его скрипт, ничего делать не надо.
2. Что это даст всем (скриптерам)? Сейчас, если в скрипте выполняется длительный участок байт-кода main, то на время его выполнения, блокируется выполнение основного потока, обрабатывающего колбеки всех запущенных скриптов пользователя и обслуживающего события таблиц QUIK. Все аналогично, если описанное выше, происходит в функции, вызванной в колбеке. ----- Для демонстрации выигрыша скриптера от реализации обсуждаемого предложения рассмотрим, например, следующую ситуацию. У пользователя запущено два скрипта (почему бы нет, они будут выполняться в разных потоках): первый скрипт продуктив, который реально торгует на рынке (обрабатывает колбеки); второй скрипт продуктив, который тоже реально торгует на рынке (обрабатывает колбеки). Если во втором/первом скрипте в какой-то момент времени будет обрабатываться длинный байт-код в main и при этом в нем вызовется колбек, то поток обработки колбеков всех скриптов будет заблокирован. При этом перестанут обслуживаться и колбеки первого/второго скрипта. Это может произойти неожиданно и в самом неподходящем месте и породить неприятные последствия для торгующего. Этого ожидает пользователь? Надо ли скриптеру, при каждой редакции своих скриптов анализировать свой код на возможность возникновения описанной ситуации или других похожих? ---- Если бы было реализовано то, что я предлагаю, то описанных выше блокировок не было бы. Кто-то скажет, что описанный выше пример надуманный, редкий и так далее. Но, те, кто разрабатывал более-менее серьезные программы, наверное, понимают, что если есть баг в программе, то рано или поздно он может проявиться. 3. И вопрос Антону: все-таки, интересно, какую конкретную функциональность в своих разработках вы реализуете, использую блокировку потоков выполнением длинных участков байт-кода?
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
31.07.2021 11:58:37
Цитата
Anton написал: А форк или не форк мне не интересно.
Ну, не я же начал про форки. А ответил потому, что подумал, что, вдруг, узнаю что-то новое.
Цитата
Anton написал: Вам стало скучно, вы придумали какую-то околесицу и пытаетесь ее всем навязать.
Насчет околесицы не согласен, почитайте наше с вами общение, начиная с комментария:
Цитата
Anton написал: Мне не нужны случайные переключения контекста посреди байткода. Мне они помешают.
Это уже интересно. Опишите как такие переключения вам мешают. Мне они никак не мешаю.
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
31.07.2021 10:37:42
Цитата
Anton написал: Того же самого я не хочу достигать, бо не вижу проблемы в существующем поведении и, более того, считаю такое поведение весьма удачным, случайно оно возникло или намеренно.
То есть, вы вполне удовлетворены тем, что QLua является «форком луа» (если вы отвергаете все остальное, приведенное мною в обоснование того, что QLua, похоже, форк ) хотя бы по причине:
Цитата
TGB написал: 1) исходники Lua были изменены для обеспечения многопотоковости QLua (смотрите мой комментарий ;
И тогда что это:
Цитата
Anton написал: вы предлагаете создать форк луа и встроить в квик именно форк. Это дорога в ад. Надеюсь, в арке это понимают.
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
31.07.2021 08:28:10
1.
Цитата
Anton написал: Там вы как раз неправильно делаете правильные вещи ) То же самое достигается без изменения кода луа.
То, что я предложил очень конкретно, работает (прочитайте эту ветку сначала). Где ваше предложение достичь того же самого без изменения кода Lua?
2. Здесь, как я понимаю, мы с вами обсуждаем конкретное предложение, протестированное на моем стенде:
Цитата
TGB написал: Прошло два месяца. Просьба к поддержки: сообщить результаты рассмотрения пожеланий. ---- Второе пожелание факультатив и, наверное, его стоит рассматривать после устранения критических ошибок, но первое пожелание (было отмечено сразу при описании пожеланий) это устранение ошибки. Напоминаю: Бывают ситуации зависания в QLua, когда основной поток обслуживания колбеков всех скриптов пользователя, а также таблиц QUIK (это не таблицы Lua), блокируется выполнением длинного цикла пользовательской программы на «чистом» Lua, в котором нет ни вызова seep ни вызова других C-функций. Это может порождать ошибки, которые для многих пользователей QLua (использующих несколько запускаемых скриптов) являются неожиданными и труднообъяснимыми. Блокируются выполнения колбеков всех скриптов из-за выполнения длинного цикла пользовательской программы на «чистом» Lua в каком-то из запущенных пользователем скриптов. ----- Есть простой вариант реализации первого пожелания, кстати, совместимого со вторым (далее список изменений реализующих этот вариант в в тексте исходни-ков Lua ): 1. В файле lstate.h после строки: lu_byte allowhook;добавить: int Счетчик_для_переключения_State; 2. В файле lstate.с после строки: L->errfunc = 0;добавить: L->Счетчик_для_переключения_State = 0; 3. В файле lstate.с после строки: L1->stacksize = BASIC_STACK_SIZE;добавить: L1->Счетчик_для_переключения_State = 0; 4. В файле lvm.с после строки: StkId ra;добавить: if (++L->Счетчик_для_переключения_State > 1000) { // 1000 надо задать кон-стантой L->Счетчик_для_переключения_State = 0; lua_unlock(L); lua_lock(L); } ------------------------------------ В чем проблема реализации первого пожелания?
Вместо того, чтобы сделать конкретные замечания по выше предложенному, вы пускаетесь в филосовские рассуждения о том, после какой, внесенной в исходники Lua запятой, считать его «форк луа». Причем, напомню вам, что по вашему же предложению (кстати, поддержанного в комментариях мною) были внесены разработчиком QUIK заметные изменения в обработку исключительных ситуаций Lua. Наверное, вы ответите, что изменения в обработку исключений не делают Lua «форком луа» .
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
30.07.2021 23:45:21
Цитата
Anton написал: TGB , вы предлагаете создать форк луа и встроить в квик именно форк. Это дорога в ад. Надеюсь, в арке это понимают.
Мне кажется, с предупреждением, вы опоздали (как всегда, "все украли до нас" ). ARQA уже создала и использует форк луа: 1) исходники Lua были изменены для обеспечения многопотоковости QLua (смотрите мой комментарий ; 2) сравните размер кода Lua (~300 кб) с размером кода QLua (более 500 кб).