finsight / QUIKSharp

QUIK# (QUIK Sharp) is the QUIK Lua interface ported to .NET.
Other
230 stars 134 forks source link

Постепенное и не контролируемое увеличение оперативной памяти #351

Closed yiv1 closed 10 months ago

yiv1 commented 10 months ago

Воспроизводится на Windows Server 2022 Терминал QUIK 10.3.6.3 Во время подключения lua скрипта, переименованы папки clibs64/53_MD и clibs64/53_MT (содержимое поменяно местами) Скрипт запускается на версии lua 5.3.5

Три скриншота: 1) Когда скрипт только подключен image

2) Когда скрипт ожидает клиентов (растет но очень медленно, спустя 8 часов) image

3) Когда скрипт передает данные клиенту (растет очень быстро, прошло около 30 минут) image

Полагаю, такая проблема уже обсуждалась в 2021 году при похожих вводных https://forum.quik.ru/forum1/topic6896/

Как это можно исправить?

Pr0phet1c commented 10 months ago

У меня главный скрипт сжирает больше (на текущий момент ~ 1 904 500KB). Вспомогательные ~500KB каждый. Но это не приводит к падению. Но речь конечно не про Server. Из приведенной Вами ссылки одним из вариантов решения был переход на другую версию Квика, где у человека все стабильно работает. Может быть проблема не в коннекторе?

yiv1 commented 10 months ago

У меня главный скрипт сжирает больше (на текущий момент ~ 1 904 500KB). Вспомогательные ~500KB каждый. Но это не приводит к падению. Но речь конечно не про Server. Из приведенной Вами ссылки одним из вариантов решения был переход на другую версию Квика, где у человека все стабильно работает. Может быть проблема не в коннекторе?

Предположим что 2гб для работы lua-скрипта нормально. Спасибо, ценная информация.

Что входит в эти 2гб? Для чего такой объем данных требуется, а главное какие данные накапливаются?

yiv1 commented 10 months ago

1,9гб не предел image

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

PS. Просто хочу риски работы скрипта понять.

yiv1 commented 10 months ago

3,5гб image

После этого начали закрываться приложения image

Есть идеи как вылечить проблему? В lua ничего не понимаю, сам не справлюсь

yiv1 commented 10 months ago

Так выглядит освобождение оперативки в момент остановки скрипта image

Pr0phet1c commented 10 months ago

К сожалению, я не могу Вам помочь. Есть вероятность, что это особенность работы QLua. Подумайте вот над чем: QUIK# это прокладка, которая по сути ничего своего в терминале не делает. Она лишь запускает (выполняет) те функции, которые заложены в QLua и описаны в справке к терминалу. Возможно, подписка на определенные колбэки или на получения свечей или на стакан приводят к накоплению каких-то данных, и это происходит не потому, что коннектор так устроен, а потому, что функция QLua так работает.

Это все мои предположения, но проверкой этой теории я сейчас заниматься не готов.

yiv1 commented 10 months ago

Так как хочу использовать именно lua-скрипты quiksharp, уделил проблеме время. Спасибо за крутую библиотеку! В lua вообще ничего не понимаю, но задача похожа на классическую утечку памяти.

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

В файле qsutils.lua

function sendCallback(msg_table)
    -- if not set explicitly then set CreatedTime "t" property here
    -- if not msg_table.t then msg_table.t = timemsec() end
    local callback_string = to_json(msg_table)
    if is_connected then
        local status, res = pcall(callback_client.send, callback_client, callback_string..'\n')
        if status and res then
            return true
        else
            disconnected()
            return nil, err
        end
    end
end

меняем на

local counter = 0

function sendCallback(msg_table)
    -- if not set explicitly then set CreatedTime "t" property here
    -- if not msg_table.t then msg_table.t = timemsec() end
    local callback_string = to_json(msg_table)
    if is_connected then
        if math.fmod(counter, 1000) == 0 then
            -- log("Memory used before: " .. math.ceil(collectgarbage("count") / 1024) .. "M", 1)
            -- log("Collecting garbage...", 1)
            collectgarbage()
            -- log("Memory used after: " .. math.ceil(collectgarbage("count") / 1024) .. "M", 1)

            counter = 0
        end

        counter = counter + 1

        local status, res = pcall(callback_client.send, callback_client, callback_string..'\n')
        if status and res then
            return true
        else
            disconnected()
            return nil, err
        end
    end
end

Результат отчистки: image Скрипт очищает память, до стартовых 500кб, после каждых 1000 "отправок"

Первичные подозрения пали на две вещи:

Дальше подозрений углубляться не стал. Текущий результат и так устраивает.

@Pr0phet1c по хорошему нужно протестировать на нескольких разных устройствах и в случае успеха сделать PR с нормальной реализацией, не на коленке.

Пока issue закрою как решенную.

Pr0phet1c commented 10 months ago

Интересное решение. А главное - простое. Потестирую у себя. если никакий проблем не всплывет - доваим этот кусок кода в рабочую версию проекта

exvion commented 10 months ago

@yiv1 А вариант перехода на lua 5.4 не рассматриваете?

yiv1 commented 10 months ago

@yiv1 А вариант перехода на lua 5.4 не рассматриваете?

Не знаю как это сделать и стоит ли. Вернее запустить пытался, но возникали ошибки, скрипт отказывался запускаться. Разбираться не было желания. А на 5.3.5 сразу заработало.

exvion commented 10 months ago

@yiv1 А вариант перехода на lua 5.4 не рассматриваете?

Не знаю как это сделать и стоит ли. Вернее запустить пытался, но возникали ошибки, скрипт отказывался запускаться. Разбираться не было желания. А на 5.3.5 сразу заработало. Внес небольшие изменения для работы с lua 5.4, только с lua 5.3 работать не будет. Попробуйте. https://github.com/exvion/QUIKSharp