not enough memory

Страницы: 1
RSS
not enough memory
 
Робот работает на виртуалке Windows Server 2003
Я обрабатываю луа-скриптом таблицу с гигантским количеством полей (запись слепков стакана за 10 дней и более).
Робот при добавлении очередного дня-таблицы со слепками в общую огромную таблицу вылетает с ошибкой
not enough memory, хотя оперативной памяти хватает.
Я добавлял на виртуалку ещё 1 ГБ опер.памяти, чтобы наверняка хватало, но всё равно скрипт вылетает с этой ошибкой.
Гуглил эту ошибку в интернете, нашёл такую ветку с обсуждением этой темы:
https://github.com/minetest/minetest/issues/2988
Нашёл там такую фразу Lua has no problem consuming 2GiB, but LuaJIT bails at 1GiB.
Вот:

Я, увы, не сильно понял в чём дело и что такое LuaJIT. Но у меня вылетает скрипт как раз на 1 гигабайте оперативки.
Прошу подсказать решение проблемы.
Также я не понял что это за код, который советует использовать комментатор. Он превращает числа в строки? Но как я это могу применить у себя?
Заранее спасибо.
 
Цитата
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 ГиБ.
 
Цитата
Let_it_go написал:
Робот работает на виртуалке Windows Server 2003
Я обрабатываю луа-скриптом таблицу с гигантским количеством полей (запись слепков стакана за 10 дней и более).
Робот при добавлении очередного дня-таблицы со слепками в общую огромную таблицу вылетает с ошибкой
not enough memory, хотя оперативной памяти хватает.
Я добавлял на виртуалку ещё 1 ГБ опер.памяти, чтобы наверняка хватало, но всё равно скрипт вылетает с этой ошибкой.
Гуглил эту ошибку в интернете, нашёл такую ветку с обсуждением этой темы:
https://github.com/minetest/minetest/issues/2988
Нашёл там такую фразу Lua has no problem consuming 2GiB, but LuaJIT bails at 1GiB.
Вот:

Я, увы, не сильно понял в чём дело и что такое LuaJIT. Но у меня вылетает скрипт как раз на 1 гигабайте оперативки.
Прошу подсказать решение проблемы.
Также я не понял что это за код, который советует использовать комментатор. Он превращает числа в строки? Но как я это могу применить у себя?
Заранее спасибо.
У Вас явно плохо написан скрипт.
-----------------------------
Вот несколько советов :
------------------------------.
1) перед загрузкой очередной порции данных поставьте collectgarbage()
-------------------------------------
2) Возможно у Вас не хватает памяти на диске
--------------------
3) измените формат хранения данных
------------------------
4) грузите в память лишь то что обрабатываете,
остальное стирайте из памяти сборщиком мусора
---------------
5) сделайте обработку на C в виде dll для луа.
----------------
6) измените алгоритм обработки данных.
 
Suntor
Ваш код сразу вешает КВИК, и его приходится принудительно закрывать. так что результата никакого нет.

Николай Камынин,
collectgarbage()  надо ставить в таком виде как вы написали или в скобках ещё какие-то аргументы?
---
И ещё.
Господа, вопрос немного другой. Мне очень долго будет оптимизировать код по совету Николая "грузите в память лишь то что обрабатываете". Я плохой кодер, а код в нынешнем виде работает и справляется с анализом 5-7 дней (его выбивает когда я хочу прочесать больше данных)
Мой вопрос следующий: можно ли обойти это ограничение Луа "not enough memory"? Или оно непобедимо?
 
П.С. Памяти как оперативной, так и на диске C хватает, это точно.
 
Цитата
Let_it_go написал:
Suntor
Ваш код сразу вешает КВИК, и его приходится принудительно закрывать. так что результата никакого нет.
Вы уверены?... почистите всё у себя. Запустите чистый Quik без настроек и без других скриптов, и проведите опыт повторно.

Единственное, на чём может повиснуть этот скрипт, так это на строчке string.rep, где создаётся строка размером 128 МиБ. Реализация функции такова, что она съедает в 4 раза больше памяти, до 600 МиБ из стека. На быстрой машине выполнение скрипта на этой строчке зависает на несколько секунд. Подозреваю, что если запустить этот скрипт на медленной машине да ещё с памятью выделенной из файла подкачки, который лежит где-нибудь на старом HDD, то зависнуть может на несколько минут... но это проблема с железом тогда у вас. Ваш собственный скрипт будет жутко тормозить и глючить в таких условиях, если он пытается обработать ГиБ данных.

Попробуйте для начала заменить:
local s = string.rep(" ", 128 * 1024 * 1024)
На:
local s = string.rep(" ", 1024 * 1024)
 
Николай Камынин, пытаюсь сделать по вашему совету. Читать новую строчку в файле и сразу обрабатывать логику.
Столкнулся с непонятным моментом.
---
Данные хранятся в файле в таком виде:


Ранее я с помощью скрипта рисовал в начале t={
а в конце
}
и исполнял этот файл с помощью dofile() Получал таблицу, а потом объединял её с другими днями-таблицами.
---
Теперь, чтобы не забивать оперативку, я делаю так:


Но прочтённые строки не воспринимаются как таблицы. Это стринг.
Посоветуйте пожалуйста как быть.
Спасибо.

Suntor, чуть позже отпишусь по вашему скрипту.
 
Suntor,
запустил первоначальный вариант кода на боевой виртуалке, на которой возникает проблема not enough memory. (подвисание квика было не на ней, а на ноутбуке).

 
Когда-то меня интересовал вопрос - какого размера таблицы я смогу создать в скрипте робота.

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. Пишу по памяти в походных условиях, основную идею передал, числа могут отличаться.
 
Цитата
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")()
 
Код
local t = loadstring("local t = "..line.." return t")()
Спасибо. Получилось.
А как обрезать запятую в конце?
Код
{data=20180430,stime=102001,stime_ms=215575.842,bid=14668,offer=14674},
пока я не понял в чём дело, запятая давала ошибку nil
 
Разобрался
Код
stroka=string.gsub (stroka, "},", "}")
такая строчка решила вопрос с запятой.
 
Друзья, как вы можете прокомментировать такую информацию с сайта Луа про функцию 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.
В нынешнем варианте мой скрипт бегает по полям гигантской таблицы, а теперь будет бегать по строчкам файла.
Не получится ли чрезмерная нагрузка на процессор, замедление работы и т.д.
Торгующий робот установлен там же где и считающий, поэтому для меня такие вещи важны.
 
Цитата
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}
 
Мда..
переписал код. Теперь оперативная память не заполняется, но продолжительность расчёта возросла невероятно.
Перебираю данные по Си за 3 дня.
Раньше на 1 итерацию (перебор всех данных за 3 дня) уходила 1 секунда, теперь 8.
У меня 10 фьючерсов, и в каждом переборе брут форсом 100 итераций.
--
Моя цель была давать ему на обработку десятки и сотни дней...  
 
Нашёл на просторах интернета рецепт как избегать ошибки луа not enough memory
описание
https://www.freelists.org/post/luajit/Extending-LuaJITs-memory-limit-to-4Gbytes
файлы
https://github.com/Neopallium/mmap_lowmem
Я неплохо знаю английский, но тут нашла коса на камень. Если не трудно, подскажите пожалуйста как применить эту рекомендацию и не навредит ли это чему-нибудь.
 
Цитата
Let_it_go написал:
Нашёл на просторах интернета рецепт как избегать ошибки луа not enough memory
описание
https://www.freelists.org/post/luajit/Extending-LuaJITs-memory-limit-to-4Gbytes
файлы
https://github.com/Neopallium/mmap_lowmem
Я неплохо знаю английский, но тут нашла коса на камень. Если не трудно, подскажите пожалуйста как применить эту рекомендацию и не навредит ли это чему-нибудь.
Это патч для LuaJIT (реализация Lua-машины с JIT-компилятором). Вам ничем не поможет, т.к. QUIK использует вшитую Lua 5.1, а не какую-либо внешнюю.
Страницы: 1
Читают тему
Наверх