Робот работает на виртуалке Windows Server 2003 Я обрабатываю луа-скриптом таблицу с гигантским количеством полей (запись слепков стакана за 10 дней и более). Робот при добавлении очередного дня-таблицы со слепками в общую огромную таблицу вылетает с ошибкой not enough memory, хотя оперативной памяти хватает. Я добавлял на виртуалку ещё 1 ГБ опер.памяти, чтобы наверняка хватало, но всё равно скрипт вылетает с этой ошибкой. Гуглил эту ошибку в интернете, нашёл такую ветку с обсуждением этой темы:
Нашёл там такую фразу Lua has no problem consuming 2GiB, but LuaJIT bails at 1GiB. Вот: Я, увы, не сильно понял в чём дело и что такое LuaJIT. Но у меня вылетает скрипт как раз на 1 гигабайте оперативки. Прошу подсказать решение проблемы. Также я не понял что это за код, который советует использовать комментатор. Он превращает числа в строки? Но как я это могу применить у себя? Заранее спасибо.
Пользователь
Сообщений: Регистрация: 10.04.2015
28.04.2018 15:46:04
Цитата
Let_it_go написал: Но у меня вылетает скрипт как раз на 1 гигабайте оперативки.
Должно быть больше, чем 1 ГиБ.
Попробуйте запустить у себя этот .lua файл:
Код
local print = message and message or print
local s = string.rep(" ", 128 * 1024 * 1024)
local t = {}
for i = 1, 1024 do
local status, errmsg = pcall(function () t[i] = s..i end)
local m = collectgarbage("count")/1024
print("Lua memory "..(status and (m - m % 0.001).." Mbytes" or "allocation failed. Error: "..errmsg))
if not status then break end
end
У меня на свежезапущенном Quik даже с десятками открытых вкладок и окон выдаёт около 2,1..2,3 ГиБ, если запускать консольным интерпретатором, то 1,4..1,5 ГиБ.
Пользователь
Сообщений: Регистрация: 30.01.2015
29.04.2018 13:08:13
Цитата
Let_it_go написал: Робот работает на виртуалке Windows Server 2003 Я обрабатываю луа-скриптом таблицу с гигантским количеством полей (запись слепков стакана за 10 дней и более). Робот при добавлении очередного дня-таблицы со слепками в общую огромную таблицу вылетает с ошибкой not enough memory, хотя оперативной памяти хватает. Я добавлял на виртуалку ещё 1 ГБ опер.памяти, чтобы наверняка хватало, но всё равно скрипт вылетает с этой ошибкой. Гуглил эту ошибку в интернете, нашёл такую ветку с обсуждением этой темы:
Нашёл там такую фразу Lua has no problem consuming 2GiB, but LuaJIT bails at 1GiB. Вот:
Я, увы, не сильно понял в чём дело и что такое LuaJIT. Но у меня вылетает скрипт как раз на 1 гигабайте оперативки. Прошу подсказать решение проблемы. Также я не понял что это за код, который советует использовать комментатор. Он превращает числа в строки? Но как я это могу применить у себя? Заранее спасибо.
У Вас явно плохо написан скрипт. ----------------------------- Вот несколько советов : ------------------------------. 1) перед загрузкой очередной порции данных поставьте collectgarbage() ------------------------------------- 2) Возможно у Вас не хватает памяти на диске -------------------- 3) измените формат хранения данных ------------------------ 4) грузите в память лишь то что обрабатываете, остальное стирайте из памяти сборщиком мусора --------------- 5) сделайте обработку на C в виде dll для луа. ---------------- 6) измените алгоритм обработки данных.
Пользователь
Сообщений: Регистрация: 29.03.2017
30.04.2018 14:20:16
Ваш код сразу вешает КВИК, и его приходится принудительно закрывать. так что результата никакого нет.
Николай Камынин, collectgarbage() надо ставить в таком виде как вы написали или в скобках ещё какие-то аргументы? --- И ещё. Господа, вопрос немного другой. Мне очень долго будет оптимизировать код по совету Николая "грузите в память лишь то что обрабатываете". Я плохой кодер, а код в нынешнем виде работает и справляется с анализом 5-7 дней (его выбивает когда я хочу прочесать больше данных) Мой вопрос следующий: можно ли обойти это ограничение Луа "not enough memory"? Или оно непобедимо?
Пользователь
Сообщений: Регистрация: 29.03.2017
30.04.2018 14:21:42
П.С. Памяти как оперативной, так и на диске C хватает, это точно.
Ваш код сразу вешает КВИК, и его приходится принудительно закрывать. так что результата никакого нет.
Вы уверены?... почистите всё у себя. Запустите чистый Quik без настроек и без других скриптов, и проведите опыт повторно.
Единственное, на чём может повиснуть этот скрипт, так это на строчке string.rep, где создаётся строка размером 128 МиБ. Реализация функции такова, что она съедает в 4 раза больше памяти, до 600 МиБ из стека. На быстрой машине выполнение скрипта на этой строчке зависает на несколько секунд. Подозреваю, что если запустить этот скрипт на медленной машине да ещё с памятью выделенной из файла подкачки, который лежит где-нибудь на старом HDD, то зависнуть может на несколько минут... но это проблема с железом тогда у вас. Ваш собственный скрипт будет жутко тормозить и глючить в таких условиях, если он пытается обработать ГиБ данных.
Попробуйте для начала заменить: local s = string.rep(" ", 128 * 1024 * 1024) На: local s = string.rep(" ", 1024 * 1024)
Пользователь
Сообщений: Регистрация: 29.03.2017
30.04.2018 19:46:49
Николай Камынин, пытаюсь сделать по вашему совету. Читать новую строчку в файле и сразу обрабатывать логику. Столкнулся с непонятным моментом. --- Данные хранятся в файле в таком виде:
Ранее я с помощью скрипта рисовал в начале t={ а в конце } и исполнял этот файл с помощью dofile() Получал таблицу, а потом объединял её с другими днями-таблицами. --- Теперь, чтобы не забивать оперативку, я делаю так:
Но прочтённые строки не воспринимаются как таблицы. Это стринг. Посоветуйте пожалуйста как быть. Спасибо.
Suntor, чуть позже отпишусь по вашему скрипту.
Пользователь
Сообщений: Регистрация: 29.03.2017
30.04.2018 19:58:15
Suntor, запустил первоначальный вариант кода на боевой виртуалке, на которой возникает проблема not enough memory. (подвисание квика было не на ней, а на ноутбуке).
Пользователь
Сообщений: Регистрация: 27.03.2016
30.04.2018 22:43:31
Когда-то меня интересовал вопрос - какого размера таблицы я смогу создать в скрипте робота.
QUIK - 32-разрядное приложению (не уверен, может уже сделали 64?). Есть ограничение на размер памяти, доступной приложению. Обычно это 2GB, но через некоторые манипуляции можно добраться до 3GB и даже до 4GB, зависит от версии Windows. У меня - Windows XP, особо упорствовать в ее ломке не стал, но к границе в 2GB подобрался близко. Контролировал по Диспетчеру задач (info.exe, виртуальная память).
Есть особенности LUA в распределении памяти под таблицы. Изначально выделяется какой-то минимум. Как только выходим за этот предел, выделяется память в 2 раза большего размера, старые данные копируются в новую память, старая память уходит в мусор. Превысили новый предел - процедура повторяется, опять удвоение, опять мусор.
Может наступить момент, когда свободного непрерывного участка памяти двойного размера может не оказаться. Получим not enough memory. В лучших попытках я получал возможность разместить таблицы суммарно за сотню миллионов элементов, выбрав почти все 2GB доступной виртуальной памяти. Меня этот результат устроил.
Теперь - почему "в лучших попытках". Я запускал скрипт сразу после загрузки QUIK, еще было несколько графиков и с десяток индикаторов.
Скрипт сначала распределял большие таблицы, типа на 64 миллиона элементов (на попытке добавить еще элемент - not enough memory), все элементы в цикле заполнял каким-то одним значением. То есть, нарастить таблицу до 128 миллионов элементов я не мог, но мог создать еще одну размера в 64 миллиона. Потом создавал таблицы по 32 миллиона элементов, потом по 16 и т. д., пока не нарывался на нехватку памяти, отступал назад и переходил на половинный размер.
Процесс распределения памяти при загрузке QUIK оказался недетерминированным, новые ли свечки или что другое влияло - мне было несущественно. Налицо было явление фрагментации памяти, я мог распределить очень много мелких таблиц, но для крупной могло не найтись непрерывного участка нужного размера.
Отсюда и естественный рецепт - разбить гигантскую таблицу на более мелкие.
Штатная уборка мусора почему-то дремала, использовал collectgarbage явным образом.
P.S. Пишу по памяти в походных условиях, основную идею передал, числа могут отличаться.
Пользователь
Сообщений: Регистрация: 10.04.2015
30.04.2018 23:28:35
Цитата
Let_it_go написал: Suntor, запустил первоначальный вариант кода на боевой виртуалке, на которой возникает проблема not enough memory. (подвисание квика было не на ней, а на ноутбуке).
Ну судя по картинке памяти у вас там кот наплакал... и что странно, что начинается с 610 МиБ, а потом идёт по 16 МиБ... то-есть, вы либо константу всё же поменяли в string.rep, но почему тогда у вас с 610 начинается, должно начинаться с 70 МиБ... ЛИБО! у вас какой-то режим стоит в вашей виртуалке по динамическому выделению памяти, который так чудит, и из-за этого у вас все проблемы. Может стоит запустить для начала на прямом железе, чтобы вы сами увидели, что у вас получается. А потом уже сравните с виртуалкой...
Цитата
Let_it_go написал: Но прочтённые строки не воспринимаются как таблицы. Это стринг. Посоветуйте пожалуйста как быть.
Вместо stroka=line Напишите
Код
local t = loadstring("local t = "..line.." return t")()
Пользователь
Сообщений: Регистрация: 29.03.2017
01.05.2018 07:49:08
Код
local t = loadstring("local t = "..line.." return t")()
Спасибо. Получилось. А как обрезать запятую в конце?
пока я не понял в чём дело, запятая давала ошибку nil
Пользователь
Сообщений: Регистрация: 29.03.2017
01.05.2018 08:23:13
Разобрался
Код
stroka=string.gsub (stroka, "},", "}")
такая строчка решила вопрос с запятой.
Пользователь
Сообщений: Регистрация: 29.03.2017
01.05.2018 08:43:45
Друзья, как вы можете прокомментировать такую информацию с сайта Луа про функцию loadstring
Цитата
The loadstring function is powerful; it must be used with care. It is also an expensive function (when compared to its alternatives) and may result in incomprehensible code. Before you use it, make sure that there is no simpler way to solve the problem at hand.
В нынешнем варианте мой скрипт бегает по полям гигантской таблицы, а теперь будет бегать по строчкам файла. Не получится ли чрезмерная нагрузка на процессор, замедление работы и т.д. Торгующий робот установлен там же где и считающий, поэтому для меня такие вещи важны.
Пользователь
Сообщений: Регистрация: 10.04.2015
02.05.2018 08:53:45
Цитата
Let_it_go написал: В нынешнем варианте мой скрипт бегает по полям гигантской таблицы, а теперь будет бегать по строчкам файла. Не получится ли чрезмерная нагрузка на процессор, замедление работы и т.д. Торгующий робот установлен там же где и считающий, поэтому для меня такие вещи важны.
Lua сделан для удобства, а не для скорости. Если нужна высокая производительность, то нужно делать отдельную DLL на другом языке программирования, где реализовывать всю сложную математику, обработку больших массивов данных и прочее... а потом, уже эту DLL подключать к Lua скрипту и использовать. Но вполне возможно, что и самого Lua вам хватит с головой. Сделайте сначала по-простому, замерьте производительность, а дальше уже будет видно, хватает вам скорости той же loadstring или нет.
Мне стало любопытно про скорость loadstring, сделал профилировку на таблице строк, и получилось, что она ровно в 10 раз медленнее по сравнению с gsub. Что вообще говоря очень даже неплохо, учитывая, что loadstring не просто пару символов в строке меняет, а компилирует её создавая целую новую функцию с возвращаемой таблицей. Прогоны на двух таблицах по 100 тыс. и по 1 млн. строк дали:
Код
n = 100000
alloc: sec = 0.193, mem = 9.429 MiB
gsub: sec = 0.142, mem = 14.571 MiB
loadstring: sec = 1.073, mem = 15.538 MiB
n = 1000000
alloc: sec = 8.812, mem = 93.877 MiB
gsub: sec = 5.438, mem = 137.766 MiB
loadstring: sec = 55.328, mem = 113.608 MiB
По объёму такие таблицы соответствуют файлам размером около 5 и 50 МиБ соответственно. Со строками вида: {a = 999999, b = 999999, c = 999999, d = 999999, f = 999999}
Пользователь
Сообщений: Регистрация: 29.03.2017
02.05.2018 14:48:24
Мда.. переписал код. Теперь оперативная память не заполняется, но продолжительность расчёта возросла невероятно. Перебираю данные по Си за 3 дня. Раньше на 1 итерацию (перебор всех данных за 3 дня) уходила 1 секунда, теперь 8. У меня 10 фьючерсов, и в каждом переборе брут форсом 100 итераций. -- Моя цель была давать ему на обработку десятки и сотни дней...
Пользователь
Сообщений: Регистрация: 29.03.2017
10.06.2018 23:23:22
Нашёл на просторах интернета рецепт как избегать ошибки луа not enough memory описание
файлы
Я неплохо знаю английский, но тут нашла коса на камень. Если не трудно, подскажите пожалуйста как применить эту рекомендацию и не навредит ли это чему-нибудь.
Пользователь
Сообщений: Регистрация: 19.09.2017
11.06.2018 02:06:18
Цитата
Let_it_go написал: Нашёл на просторах интернета рецепт как избегать ошибки луа not enough memory описание
файлы
Я неплохо знаю английский, но тут нашла коса на камень. Если не трудно, подскажите пожалуйста как применить эту рекомендацию и не навредит ли это чему-нибудь.
Это патч для LuaJIT (реализация Lua-машины с JIT-компилятором). Вам ничем не поможет, т.к. QUIK использует вшитую Lua 5.1, а не какую-либо внешнюю.