[BUG] Повышенная загрузка CPU при большом количестве функций в скрипте
Пользователь
Сообщений: Регистрация: 12.05.2020
08.12.2021 16:04:18
Цитата
Владимир написал: На месте техподдержки я бы то же самое сказал и о приведенном коде. Ну, выполняется эта хрень в 16,25 раз дольше чем в QUIK 8.13.1.16 - и чего? Самое разумное - отправить весь код на помойку, не читая.
Я бы папуасам не рискнул объяснять, что такое тензорное исчисление, но у меня есть надежда, что поддержка не папуасы ---- Вообще то, новые версии QLua у разработчика QUIK должны проходить хотя бы простейшие тесты. Например, без подключения к серверу: 1) проверка подключения пакетов; 2) проверка скорости выполнения циклических операций; 3) проверка работа таблиц: - скорости создания таблиц; - скорости доступа к элементов И так далее …… ---- Неужели этого у разработчика QUIK до сих пор нет таких тестов?
[BUG] Повышенная загрузка CPU при большом количестве функций в скрипте
Пользователь
Сообщений: Регистрация: 12.05.2020
08.12.2021 15:23:37
Имеется ввиду строка: for i = 1, N do hour = {} end
[BUG] Повышенная загрузка CPU при большом количестве функций в скрипте
Пользователь
Сообщений: Регистрация: 12.05.2020
08.12.2021 15:21:04
В ниже приведенном коде выделена строка символами ###, которая в QUIK 9.3.1.11 (QLua 5.4) выполняется в 16,25 раз дольше чем в QUIK 8.13.1.16 (QLua 5.4) Где поддержка??
Код
--- Загрузка CPU ---
IsRun = true
function main()
local T
local hour = 0, N
N = 1000000
-------------------
while IsRun do
T = os.clock()
for i = 1, N do hour = {} end
T = (os.clock() -T) * 1000 / N ---- ### !! Без подключения к серверу: 1) В QUIK 8.13.1.16 (QLua 5.4) T = 0,00016 ;
--- 2) В QUIK 9.3.1.11 (QLua 5.4) T = 0,0026 ??? (в 16,25 раз дольше)
message (tostring(T))
sleep(500)
end
------------------
end
function OnStop()
IsRun = false
return 10000
end
[BUG] Повышенная загрузка CPU при большом количестве функций в скрипте
Пользователь
Сообщений: Регистрация: 12.05.2020
06.12.2021 23:03:58
Цитата
_sk_ написал: Думаю, что очень актуальный вопрос поднят. Спасибо топик-стартеру за демонстрацию проблемы. От разработчиков терминала ждём пояснений.
Присоеденяюсь. ----- Деградация эффективности QLua показатель низкого качества реализации разработчиками QUIK встраивания Lua в QUIK. Эффективность выполнения скриптов QLua без обращения к API QUIK должна отличаться от Lua только затратами на операции lock/unlock в вызовах функций C-API QLua, а также в VM-QLua (ulock/lock) при вызове C-функций. Причем упомянутые операции в подавляющих случаях «холостые» (потоки не переключают). Все места вызова lock/unlock (ulock/lock) определены в кодах Lua разработчиком Lua. Разработчику QUIK достаточно корректно реализовать lock/unlock, например, используя критические секции, обеспечивающие эффективную синхронизацию. Вопрос к поддержке: какое «ноу-хау» обеспечивает деградацию эффективности QLua новых версий? -----
Цитата
Anton написал: Сложился паззл. Когда в девятой версии смотрел "чего нового" в отладчике, увидел, что после каждого колбека lua_gc добавили.
Интересное открытие (пишу без иронии). Вопрос к поддержке: a это зачем сделали? Хотелось бы чтобы разработчик QUIK пояснил как додумался до этого. Какие проблемы это решает?
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
25.11.2021 19:26:27
Цитата
Старатель написал: QUIK 9.3.1.11, Lua 5.4Ещё парочка "неуловимых" косяков. Обе ошибки были в main. Никаких сторонних библиотек не подключено, только QLua-код.
Итак, в Qlua 5.4 есть «плавающая» ошибка (скорее всего ошибка синхронизации). --- «Простой» тест, диагностирующий некорректную обработку колбеков в QLua 5.3, появился у меня в результате анализа «мерцающей» ошибки в скрипте, похожей на ошибки в QLua 5.4, описанные Старателем, когда в переменной сразу после присвоения ей значения, это значение на следующем шаге оказывалось искаженным. Нельзя исключать, что природа ошибок, обнаруженных Старателем и мною одна и та же. Притом, что обсуждаемый тест ошибку в QLua 5.4 не показывает на коротком интервале времени, это совсем не значит, что такой ошибки в QLua 5.4 нет. Дело в том, что проявление ошибок синхронизации по времени может сильно зависеть и от того какая версия QLua используется. Я могу ошибаться, но, скорее всего, схемы синхронизации потоков в QLua 5.3 и в QLua 5.4 аналогичны. Поэтому, если бы разработчик QUIK, нашел бы ошибку в QLua 5.3, то он бы, наверное, нашел бы ее и в QLua 5.4. Обсуждаемый тест воспроизводит ошибку (в описанных мною условиях) в QLua 5.3 в интервале 2-3 мин. с локализацией места с точностью одной строки кода.
Основные библиотеки для QLua 5.4.1
Пользователь
Сообщений: Регистрация: 12.05.2020
21.11.2021 12:40:32
Пакеты для Lua 5.4: iup, lfs, sqlite3 Lua - файлы для сборки пакетов под Lua 5.4.
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
15.11.2021 16:07:45
Цитата
Alexey Ivannikov написал: Информация получена, проблема изучается. Постараемся в ближайшее время дать ответ.
Появилась очередная версия QUIK 9.3.1.11. В этой версии проблема существует.
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
12.11.2021 16:49:01
Цитата
Alexey Ivannikov написал: Добрый день.Результат разбора был передан Вам в сообщении 84 (выше). Если Вы не согласны с данной резолюцией - просьба подробно описать почему, мы передадим эту информацию разработчикам.
Здравствуйте. Действительно, обсуждаемую ошибку в QLua 5.4 я не наблюдал. Но, если разработчик QUIK поддерживает и QLua 5.3, то, наверное, надо эту ошибку устранить и в QLua 5.3. Тем более, что эта ошибка базовой функциональности обработки колбеков. Причем, тест , диагностирующий ошибку мною упрощен до такой степени, что проявление ошибки в коде теста локализовано в пределах одной строки, помеченной комментарием --- ###. Этот тест разработчик может использовать при поиске ошибки в QLua. Просьба передать его коды и описание ошибки в комментарии разработчику QUIK.
В предыдущем моем комментарии у меня не было времени подробно пояснить, что понимается под схемой использования Lua во многих потоках. Попробую это сделать сейчас. Главный thread и остальные thread Lua пространственно, по стеку, разделены и поэтому могли бы обрабатываться в разных потоках без синхронизации. Но не допустима обработка любого thread в нескольких потоках. Если в разных thread нет общих модифицируемых данных, то синхронизация между thread не требовалась бы. Казалось бы, thread могли бы работать параллельно, синхронизируясь только на общих модифицируемых данных. Однако, в Lua есть «общее хозяйство» всех thread , требующее синхронизацию – это общая автоматическая память Lua, поддерживаемая мусорщиком, «заточенным» разработчиками Lua только на однопоточное использование. Поэтому VM-Lua можно использовать в разных потоках только в разделяемом режиме. В любой момент времени VM-Lua может обрабатывать только один поток.
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
04.11.2021 20:48:34
Цитата
Anton написал: В общем случае в 5.3 замыкание может создаваться небезопасно
При корректной синхронизации (в тех местах кода Lua, определенных разработчиком Lua) в той схеме, которую определили разработчики Lua для использования ее во многих потоках, почему? Не понял. В этой схеме работа Lua эквивалентна ее однопоточному использованию. Я это проверял и пока ошибок у разработчиков Lua не обнаружил.
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
04.11.2021 13:49:12
Цитата
Alexey Ivannikov написал: Поведение Lua 5.4 считаем правильным, т.е. именно таким, каким было задумано её автором, и рекомендуем использовать именно её.
Здравствуйте. Действительно, обсуждаемую ошибку в QLua 5.4 я не наблюдал. Но, если разработчик QUIK поддерживает и QLua 5.3, то, наверное, надо эту ошибку устранить и в QLua 5.3. Тем более, что эта ошибка базовой функциональности обработки колбеков. Причем, тест , диагностирующий ошибку мною упрощен до такой степени, что проявление ошибки в коде теста локализовано в пределах одной строки, помеченной комментарием --- ###.
[ Закрыто] Ищу спеца по ЛуаКвик, для долгосрочного сотрудничества по созданию робота и его доработкам или для консультаций и наставничества.
Пользователь
Сообщений: Регистрация: 12.05.2020
26.10.2021 23:53:59
Я поддерживаю поддержку QUIK в стремлении навести порядок на форуме. Здесь не подворотня. «Стычки» между пользователями, конечно, допустимы (в профессиональных рамках), но без перехода на личности. Как мне представляется, «грязный» спам, не имеющий отношение к обсуждаемой теме, поддержка может удалять исходя из своих представлений без объяснения своих мотивов. Миндальничать, наверное, не надо.
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
10.10.2021 14:22:34
Цитата
Anton написал: нет квика под рукой, посмотрите плиз, вот так воспроизведется?
Да
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
10.10.2021 10:11:57
Цитата
Daniil Pozdnyakov написал: спасибо за Ваш комментарий, он будет учтён при разборе.
Тест, описанный в комментарии (10.09.2021) упростился (строка с проблемным кодом помечена символом ###):
Код
local for_OnParam = 2 -- Множитель
local N_OnParam = 0
----
function OnParam(p1, p2)
for i = 1, for_OnParam do
N_OnParam = N_OnParam + 1
end
end
---
--------
IsRun = true
function main()
local J
local OnParam_begin
-------------------
while IsRun do
------
do
OnParam_begin = N_OnParam
J = 100000000
while ( J > 0 ) do J = J - 1 end -- ### Проблема здесь. "Чистый" байт-код, но в QLua 5.3 здесь переключаются потоки (! в 5.4 этого нет)----
-- for i = 1, 100000000 do end -- Это в QLua 5.3 работает нормально ---
if N_OnParam ~= OnParam_begin then -- Счетчик N_OnParam может исмениться только в OnParam
message ( ' Переключение колбека и потока main: N_OnParam - OnParam_begin = ' .. tostring(N_OnParam - OnParam_begin))
end
end
-----
sleep(10)
end
------------------
end
function OnStop()
IsRun = false
return 10000
end
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
07.10.2021 10:21:55
Цитата
Anton написал: Соответственно причина явно не в этом.
Согласен. luaL_setfuncs не применима к функциям Lua, а только к С-функциям. --- Эксперименты показали, что проблема в lua_pcall (нет блокировки доступа к байт-кодам). Либо в этой функции нет синхронизации в QLua 5.3 (что очень сомнительно), либо в ней не корректно указана ссылка на объект синхронизации (он должен быть общим для всех lua_State скрипта).
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
05.10.2021 14:40:44
Цитата
Anton написал: Этот параметр указывает количество upvalues, прицепленных к каждой функции. Их можно и к сишным функциям прицепить. Соответственно причина явно не в этом.
Вообще, мне (и остальным пользователям QUIK) не интересны причины наблюдаемой ошибки. Нам существенно, чтобы эта ошибка была устранена.
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
05.10.2021 14:11:09
Цитата
Daniil Pozdnyakov написал: Проблема, о которой Вы говорите, на данный момент изучается, и, к сожалению, какую-либо резолюцию, а также сроки решения данной задачи дать не можем.
Долго изучаете проблему. Не точно, но скорее всего, колбеки регистрируются в QLua (а этого можно и не делать - смотрите мои комментарии) с помощью функции: void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) и, наверное, с параметром nup = 0. Параметр nup = 0 означает, что это C - функции и они запускаются без блокировки байт-кодов. Что является ошибкой. ---- Возможно, я ошибаюсь, и все-таки просьба к поддержке: донести этот комментарий до разработчиков QUIK.
Выскакивает ворнинг "Compare string with number", А его не должно быть, по идее!
Зачем смуту сеете в «неокрепшие» умы ? --- Даже если ядро одно, то все равно может сброситься. Потоки и при одном ядре переключаются по времени из-за выделения им квантов процессорного времени. Переключение на выполнение потока колбека может случиться сразу после проверки в main: os.time () > Time. И тогда Time может сброситься при выполнении колбека.
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
01.10.2021 22:41:23
Цитата
Daniil Pozdnyakov написал: Ваше письмо получено, проблема изучается. Постараемся в ближайшее время дать ответ.
Здравствуйте! Появилась версия QUIK 9.2.2.11 (с обновлениями). В этой версии в QLua 5.3 тест, описанный в комментарии (10.09.2021) демонстрирует ошибку в запусках колбеков. Эта ошибка может проявляться как случайные сбои в сриптах пользователей в различные моменты времени. В версии в QLua 5.4 ошибка не проявляется У поддержки есть вопросы по тесту?
Расширить список функций обратного вызова
Пользователь
Сообщений: Регистрация: 12.05.2020
29.09.2021 10:37:08
1. nikolz зачем при ссылке на мой код процитировали его весь? Он все-таки длинный и достаточно было бы привести несколько строк. У вас что, есть план по объему генерации текстов своих комментариев ? 2. Это
вы написали не случайно ? А если так, то можно предположить, что это разрешение вашего гипотетического таймера, который вы собираетесь создать (готового пока у вас я не вижу ничего) используя
Цитата
nikolz написал: пул событий на основе WaitForMultipleObjects.
Разрешение таймера в 0.1 мкс в Windows (только не путайте с возможностью засечки времени в Windows с использованием QueryPerformanceCounter) было бы круто не только для QLua, но и для C. Я, правда, не очень понимаю, зачем такое разрешение нужно в QLua, но ваша заява так впечатляет и претендует на открытие, что мне стало интересно, а вдруг вы Кулибин от программирования . Вам известно, что интервалы в WaitForMultipleObjects можно задать только в млсек.? Вообще, расскажите подробно в деталях, что вам известно о WaitForMultipleObjects (возможно, неизвестное мне), позволяющее, по-вашему, мнению, использовать эту функцию для обеспечения разрешения вашего гипотетического таймера в 0.1 мкс. Только не рассказывайте, это на «растопыренных» пальцах, а приведите нормальное API и к нему нормальный код (лучше, ваш, работающий, или хотя бы, найденный в сети) на каком-нибудь, известном вам языке программирования. Я попытаюсь такой код понять и как то его прокомментировать.
Расширить список функций обратного вызова
Пользователь
Сообщений: Регистрация: 12.05.2020
27.09.2021 17:23:03
Цитата
nikolz написал: Реализовал это, создав пул событий на основе WaitForMultipleObjects. В итоге бесконечный цикл запускается через заданный в функции ожидания интервал,т е это тайме собаки,либо при срабатывании любого колбека QLUA или любой функции пользователя, для которой описано событие. При возникновении события запускается соответствующий ему колбек. Количество событий- любое. Количество колбеков- любое. Все события контролируются OC. Примерно так.
И это весь ваш (очень простой ) работающий код, который я могу запустить на своем ПК с тем, чтобы проверить, как он замечательно работает? --
Ну, если бы приведенный вами «код» работал бы, то это было бы, конечно, большое достижение, особенно с учетом того, что все исполняемые приложения контролируются ОС .
библиотека для sqlite
Пользователь
Сообщений: Регистрация: 12.05.2020
27.09.2021 16:19:35
По ссылке расположены коды для работы из QLua (5.3, 5.4) c базами SQLite. !! Файл sqlite3.dll одинаковый для 5.3 и 5.4. Простой вариант подключения к пакету: 1) Переслать файлы варианта 5.3, либо 5.4 в папку с info.exe 2) В скрипте подключиться к пакету следующим образом
Код
local WorkingFolder = getWorkingFolder()
package.cpath = package.cpath .. ';' .. WorkingFolder .. '\\?3.dll' -- C - пакеты ----
sqlite3 = require('lsqlite3'); ------ Подключение пакета работы с sqlite3 -----
---- Далее использовать функции работы с базами: sqlite3.<Функция работы с базами>
При таком подключении можно использовать коды только либо для Lua 5.3, либо для Lua 5.4. Сделать автоматический выбор пакетов в зависимости от того как запускается скрипт (Lua 5.3 или Lua 5.4) несложно.
Расширить список функций обратного вызова
Пользователь
Сообщений: Регистрация: 12.05.2020
25.09.2021 11:33:22
3.
Цитата
nikolz написал: Вы может сами добавить сколько хотите функций обратного вызова.
Вы что, не поняли и то, что в приведенном мною примере демонстрируется возможность создания таймерных событий столько, сколько потребуется?
Расширить список функций обратного вызова
Пользователь
Сообщений: Регистрация: 12.05.2020
25.09.2021 08:05:32
1.
Цитата
nikolz написал: Попробуйте использовать таймеры ожидания (таймеры ядра)Такое решение и проще и лучше. Не надо создавать новые потоки.Квант таймера 0.1 мкс.Программирование гораздо проще, чем ваша скатерть-самобранка.
Ну. про это я, наверное, знаю. А вы попробуйте привести здесь свой работающий код и тогда поговорим.
2. Тот кто соображает, поймет, что выложенный мною модуль обеспечивает возможность запускать пользователю свои функции в отдельном (от основного потока QUIK) потоке.
Расширить список функций обратного вызова
Пользователь
Сообщений: Регистрация: 12.05.2020
25.09.2021 00:08:09
Извините не заметил искажения автора цитаты. В предыдущем комментарии цитата Старателя
Расширить список функций обратного вызова
Пользователь
Сообщений: Регистрация: 12.05.2020
25.09.2021 00:04:32
Нужно ли переносить функциональность скрипта в основной поток с учетом написанного мною в предыдущем комментарии, а также с учетом цитируемого ниже?
Цитата
TGB написал: Таблицы обслуживаются только в одном основном потоке. Доступ к данным - тоже только в одном потоке.Так что все ваши "несколько скриптов" дружно встают в очередь, как только им понадобится что-то вывести в таблицу. И включаются в общую конкурсную массу вмести с другими таблицами и графиками.
Ответ разработчика QUIK (документ «Использование Lua в Рабочем месте QUIK»): «При использовании событийной модели Lua скрипт выполняется в двух потоках: функции обратного вызова выполняются в основном потоке РМ QUIK, а функция main() в до-полнительном потоке РМ QUIK (подробнее см. п. 1). При этом для предотвращения «подвисаний» РМ QUIK необходимо каким-либо образом оптимизировать сценарии, описан-ные в функциях обратного вызова. Одним из способов такой оптимизации является перенос логики обработки полученных сигналов в функцию main(). Данный подход сводит количество сценариев в функции обратного вызова до одного, а именно добавление в глобальную Lua таблицу (очередь) записи о том, что функция сработала и вернула определённые значения. Таким образом, мы получаем очередь событий, которые необходимо обработать в другом потоке.» ----- Если кому интересно, то в моем комментарии выложен код реализации модуля обработки событий колбеков и событий таблиц QUIK с использованием очередей. Там же приведен скрипт-шаблон подключения модуля и при-мер его использования. При использовании очередей проблем синхронизации нет вообще. Основной поток выполняет по событиям QUIK только короткие записи параметров колбеков в очереди, которые обрабатываются в потоке main.
Расширить список функций обратного вызова
Пользователь
Сообщений: Регистрация: 12.05.2020
24.09.2021 19:21:24
Цитата
Старатель написал: Цитата TGB написал: перенос коротких задач пользователя в колбеки делает скрипт пользователя многопоточным, то есть, при этом пользователю нужно следить за тем, нет ли в его скрипте проблем синхронизации.
В данной ветке, наоборот, обсуждение, переноса задачи, выполняемой по таймеру, в основной поток, чтобы не заморачиваться синхронизацией: Цитата _sk_ написал: удобно иметь возможность инициировать какой-то коллбэк из потока main, не надо думать про синхронизацию
Из выше приведенного я понял, что о синхронизации мною было написано слишком лапидарно и не очень понятно. Попробую пояснить это более детально. Проблемы синхронизации возникают, только в случае, если у двух или более потоков есть общие модифицируемые при обработке данные. Поэтому при обработке колбеков, до тех пор, пока в main есть только цикл со sleep, то синхронизацией можно не озадачиваться. Но как только, после очередного внесения изменений в скрип, появятся общие для функций колбеков и функций main модифицируемые данные, с синхронизацией следует разбираться. Причем, проблемы синхронизации возникают не в отдельных потоках, а при их взаимодействии. Конечно, можно всю функциональность скрипта перенести в основной (единственный) поток QUIK и не будет никаких проблем с синхронизацией. Надо только следить за тем, чтобы при изменении скрипта не появились общие (для main и основного потокаQUIK) модифицируемые данные.
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
23.09.2021 13:37:45
Цитата
Anton написал: Как только ядер больше одного, тут же начинают весьма себе блокировать.
То есть, для вас чем меньше ядер у ПК, тем лучше?
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
23.09.2021 12:36:11
Цитата
Anton написал: Выделил ключевое. Как только ядер больше одного, тут же начинают весьма себе блокировать.
То есть. когда вы пользуетесь браузером, у вас QUIK перестает работать?
Цитата
Anton написал: Устройте его себе сами . Потом расскажете, удобно ли.
Рассказываю. То что я уже устроил себе, мне удобно.
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
23.09.2021 11:42:41
Цитата
Старатель написал: TGB , в одном месте вы пишите , что байт-код не должен прерываться, в другом наоборот. Вас двое что ли?
Не надо комплиментов насчет того, что я могу заменить двоих . Нужно все-таки отличать настоящее и будущее. Вы что. не понимаете разницу между настоящим и будущим? Или притворяетесь? В настоящем байт-код в QLua не должен прерываться (так это сейчас "коряво" реализовано), а я пишу о "светлом" будущем, когда длинные участки участки непрерывного байт-кода не должны блокировать друг друга. Когда вы работаете в любой операционной системе на ПК с одним одним ядром ЦП, то при том что ядро одно, выполнение нескольких приложений в этих ОС не блокируют друг друга, а получают свой кванты ЦП. Про это вам известно?
Отладка QUIK 8.13
Пользователь
Сообщений: Регистрация: 12.05.2020
23.09.2021 07:33:57
Цитата
Roman Azarov написал: TGB , добрый день! Оба пожелания зарегистрированы, мы постараемся их рассмотреть. Впоследствии, по результатам анализа, будет приниматься решение о реализации пожеланий в будущих версиях ПО. Каких-либо сроков назвать не можем. Как будет результат анализа пожеланий, мы сообщим Вам в данной теме.
Сегодя 23.09.21. С тех пор прошло более четырех месяцев. Где результат рассмотрения? Просьба к поддержке: сообщить результат рассмотрения первого пожелания (изложенного мною, с протестированным вариантом его реализации в виде конкретного кода), устраняющего блокировку потоков длинными участками байт-кода. У вас есть замечания относительно предложенного мною кода? Я готов дать развернутый комментарий. ---- !! Второе пожелание факультатив и, наверное, его не стоит реализовывать. Оно не устраняет ошибок в QLua, достаточно сложное в реализации для разработчиков QUIK (и при некорректной реализации может внести ошибки в QLua) и, наверное, не актуально для большинства пользователей QUIK.
Расширить список функций обратного вызова
Пользователь
Сообщений: Регистрация: 12.05.2020
22.09.2021 23:35:20
Цитата
_sk_ написал: Добавить функцию обратного вызова OnTimer(), которая будет вызываться терминалом с некоторой периодичностью
В данном комментарии выложен модуль работы с таймерными событиями в отдельном потоке и шаблон его использования. ---- API работы с таймерными событиями: 1) Start_Timer() - запуск отдельного потока обработки таймерных событий. 2) <Ключ события> = Set_Timer ( {<Имя события>, <Интервал в млсек.>, <Функция обработки события>,{<Список парвметров функции>}} ) - запрос таймерного события. Через <Интервал в млсек.> будет запущена в отдельном потоке <Функция обработки события> со <Списоком парвметров функции>. 3) delete_Timer (<Ключ события>) – удаление при необходимости запрошенного собы-тия. ---- Модуль и две dll (service53.dll и service54.dll) , скачанные по ссылке: необходимо положить в папку хранения info.exe. --- Модуль OnTimer (для QLua 5.3 и 5.4):
Код
-- Модуль таймерных событий OnTimer ---
-- Подключение C-пакетов service53, service54: https://cloud.mail.ru/public/i3Y7/kQHBvs7um
local WorkingFolder = getWorkingFolder()
package.cpath = package.cpath .. ';' .. WorkingFolder .. '\\?.dll' .. ';' .. WorkingFolder .. '\\?53.dll'.. ';' .. WorkingFolder .. '\\?54.dll' .. ';' .. WorkingFolder .. '\\?51.dll'
.. ';' .. WorkingFolder .. '\\?3.dll' -- C - пакеты ----
if _VERSION == 'Lua 5.3' then
require('service53') -- Подключает библиотеку service.dll, расположенную в корневом каталоге терминала QUIK (там где info.exe) ----
else
require('service54')
end
local GetMilliseconds, Start_thread = service.GetMilliseconds, service.Start_thread
--- Функции работы с очередями ---
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 Queue_Timer = new() --- Таймерные события -----
local Queue_Timer_Sl = new() --- Очередь отмены событий ---
-------------------------------------------
--- Заказ таймерных событий ----
--- Таймерное событие: {<Имя события>, <Интервал в млсек.>, <Функция обработки события>,{<Список парвметров функции>}}
local function Set_Timer (self)
if type(self) == 'table' then
if #self >= 3 then
self [2] = self [2] + GetMilliseconds()
return push (Queue_Timer, self)
else
message ( '!!! Ошибка. Должно быть: {<Имя события>, <Интервал в млсек.>, <Функция обработки события>,{<Список парвметров функции>}}')
end
else
message ( '!!! Ошибка (параметр не таблица). Должно быть: {<Имя события>, <Интервал в млсек.>, <Функция обработки события>,{<Список парвметров функции>}}')
end
end
-----
local function delete_Timer (kl)
push (Queue_Timer_Sl, kl)
end
------
local function Timer ()
local ms, first_q
while IsRun do
--- Обработка удалений событий ---
ms, first_q = pop (Queue_Timer_Sl)
while ms do
if Queue_Timer [ms] then Queue_Timer [ms] = nil end
ms, first_q = pop (Queue_Timer_Sl)
end
--- Чтение очереди заказанных событий[ -----
for k, v in next, Queue_Timer do
if type(k) == 'number' then
if v [2] <= GetMilliseconds() then
Queue_Timer [k] = nil
if v[4] then
pcall ( v[3], table.unpack (v[4]))
else
pcall ( v[3]) -- функция без параметров ---
end
end
end
end
-------------------------------------------------------
sleep(2)
end
end
---------------------------------------
local function Start_Timer ()
Start_thread (Timer)
end
------
return {Set_Timer = Set_Timer, delete_Timer = delete_Timer, Start_Timer = Start_Timer }
---------------------------------------------
Шаблон использования модуля:
Код
-- Шаблон использования модуля таймерных событий
local OnTi mer = require('OnTimer') -- Подключение модуля обработки таймерных событий ---
local Set_Timer = OnTimer.Set_Timer
local delete_Timer = OnTimer.delete_Timer
local Start_Timer = OnTimer.Start_Timer
IsRun = true
local function call_Timer (kl)
message ( 'call_Timer = ' .. kl)
end
local function call_Timer1 ()
message ( 'call_Timer1 () ==============')
end
function main()
Start_Timer()
local kl
--- Заказ таймерных событий ----
--- Таймерное событие: {<Имя события>, <Интервал в млсек.>, <Функция обработки события>,{<Список парвметров функции>}}
kl = Set_Timer({'Set_Timer', 100, call_Timer, {100}})
kl = Set_Timer({'Set_Timer', 1000, call_Timer, {1000}})
kl = Set_Timer({'Set_Timer', 5000, call_Timer, {5000}})
kl = Set_Timer({'Set_Timer', 3000, call_Timer1})
-- delete_Timer (kl)
-------------------
while IsRun do
---- Обработка в main остального -----
kl = Set_Timer({'Set_Timer', 1000, call_Timer, {1000}})
delete_Timer (kl)
---- Конец Обработка в main остального -----
sleep(500)
end
------------------
end
function OnStop()
IsRun = false
DestroyTable(TableQUIK)
DestroyTable(TableQUIK1)
return 10000 -- !! По истечении этого интервала времени (в млсек.), данного скрипту на завершение работы, функция main() завершается принудительно.
-- При этом возможна потеря системных ресурсов. ! Если функция не выдает значение, то по умолчанию оно 5000 (5 сек.)
end
Расширить список функций обратного вызова
Пользователь
Сообщений: Регистрация: 12.05.2020
21.09.2021 22:02:41
Цитата
Старатель написал: Кто сказал "нагружать"? Задачи на 0.1-2 мс, без фанатизма.Я даже не понимаю тех, кто в стремлении "разгрузить" основной поток перекидывает простейшие задачи (с временем выполнения менее 2 мс) из колбеков в main (что опять же не бесплатно в плане нагрузки), создавая километровые очереди и забывая об общей производительности.
С написанным можно бы согласиться, но с учетом следующих моментов: 1) байт-коды основного потока QUIK и пользовательского потока main выполняются последовательно и пока выполняется один, другой ждет; то есть использование основного потока для выполнения функций пользователя параллелизм добавляет только при выполнении C-функций; 2) если у пользователя запущено несколько скриптов, то пока основной поток QUIK выполняется в одном из скриптов, он перестает обслуживать другие скрипты пользователя (в том числе, и созданные им таблицы QUIK); 3) вами выложены в ветке «Кривые ошибки в QLUA» очень эффективные потокобезопасные функции работы с очередями без синхронизации между основным потоком QUIK и потоком main; 4) перенос коротких задач пользователя в колбеки делает скрипт пользователя многопоточным, то есть, при этом пользователю нужно следить за тем, нет ли в его скрипте проблем синхронизации.
Расширить список функций обратного вызова
Пользователь
Сообщений: Регистрация: 12.05.2020
21.09.2021 11:33:48
Цитата
Nikolay написал: Да, но зачем нагружать поток терминала, пусть себе в сторонке что-то делается. Тогда можно было бы и нагруженные модули писать. Сейчас же в основном потоке только данные заполнить в общей области видимости, никаких ожиданий и долгих вычислений.
Справедливое замечание. Конечно, между колбеками и функцией main, следует создавать очереди, которые потокобезопасны, но кто это понимает? Большинство из тех, кто заходит на этот сайт, не проффесоналы.
Расширить список функций обратного вызова
Пользователь
Сообщений: Регистрация: 12.05.2020
21.09.2021 11:10:09
Цитата
Nikolay написал: Ну если уж просить, почему бы не попросить еще один поток для своих колбеков. Т.е. реализовать методы регистрации своих функций обратного вызова и отдельный поток для них, чтобы не лезть в основной поток вовсе.
То есть, это то что, реализовано в OS_Quesha. У меня есть гипотеза, почему это, до сих пор. не доступно для многих пользователей QUIK, но объявлять это не корректно.
Подскажите как отправлять инфу из QUIK в телеграм?
Пользователь
Сообщений: Регистрация: 12.05.2020
21.09.2021 10:58:30
Цитата
Nikolay написал: Если простыми словами - то это функция объект с своей областью видимости. Что дает возможность создавать разные экземпляры функции с своими переменными.
А если совсем по-простому, то это модуль, сохраняющий свое состояние (историю своего запуска) между своими запусками на исполнение.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Пользователь
Сообщений: Регистрация: 12.05.2020
21.09.2021 10:15:08
Средства отладки OS_Quesha. В OS_Quesha средства отладки представлены на трех уровнях: 1) Отладка кода; 2) Отладка приложения на уровне взаимодействия их потоков; 3) Отладка стратегий торговли на фондовом рынке. Для отладки кода обеспечены следующие возможности: 1) Ведется потокобезопасный журнал отладки, представляющий собой циклический буфер, реализованный с использованием двух текстовых файлов, между которыми выполняется переключение при заполнении текущего файла. Этот буфер обеспечивает корректную запись сообщений из различных потоков OS_Quesha с высокой частотой. Размер этого буфера задается в глобальных настройках переменной Size_log в кб. События в журнал записываются с точностью до 1 миллисекунды; 2) Печать в скрипте функцией dump_str переменных любых типов, в том числе таблиц QLua со всем их содержимым произвольной вложенности (с существующими метатаблицами); 3) Онлайн печать (при реальной работе) из меню любых глобальных переменных вместе с их содержимым; 4) Использование в скрипте Pcall_dll, обеспечивающей выполнение функций в защищенном режиме, с централизованной выдачей стека вызова функции в случае возникновения исключений. Дополнительно, если это требуется, многопоточное приложение, в котором возникло такое исключение, останавливается для после-дующего анализа возникшей ошибки; 5) Использование функции paramete_control для контроля типов параметров, вызываемых функций; 6) обработка высокочастотных сообщений об ошибках. Для отладки приложения на уровне взаимодействия их потоков можно использовать: 1) Настраиваемый, мало влияющий на функционирование приложения, фильтрую-щий вывод сообщений очередей взаимодействия потоков приложения, с привязкой их ко времени, показывающему динамическую картину, в этих очередях; 2) Команду запуска скриптов из меню отладки, обеспечивающую отладку фрагментов разрабатываемых программ в среде OS_Quesha, в процессе продуктивного функционирования приложения; 3) Команды Останов / Пуск, обеспечивающие «замораживание»/«размораживание» потоков приложения для возможности анализа их состояния. Отладка стратегий торговли на фондовом рынке обеспечивается: 1) Интерфейсом прогона стратегий торговли на внутренних данных QUIK и истории ко-тировок бумаг, хранимых в базах SQLite; 2) Оперативно сохраняемой историей одноминуток и пятиминуток конкретных, заданных в настройках бумаг, хранимых в базах SQLite; 3) Оперативно обновляемой историей данных по 18 параметрам (конкретных, заданных в настройках бумаг), получаемых по событиям OnParam, с задержкой (относительно этих событий) < 1 млсек. и записываемых в вектора в оперативной памяти; 4) Реализацией виртуальных операций на реальном рынке.
Хотелось бы увидеть ваш комментарий (с возможными возражениями), но конкретный, с указанием строк в выложенном мною тесте. ----
Цитата
Daniil Pozdnyakov написал: Ваше письмо получено, проблема изучается. Постараемся в ближайшее время дать ответ.
Спасибо. Буду ждать обновления QUIK и после этого запускать свой тест.
Кривые шибки в QLua
Пользователь
Сообщений: Регистрация: 12.05.2020
14.09.2021 12:04:09
Где реакция поддержки? ---- Третий раз (первый комментарий был написан 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