Krutoy 1 169 Опубликовано: 16 апреля, 2015 (изменено) Для работы крутой черепашки мне потребовалось быстро сериализировать и передавать по сети большие объемы информации. 3д массивы, таблицы, и прочее прочее. Внутренние методы СС Textutils.serialize не подходили, из за медленного оператора ".." , который добавлял в итоговую строку символы. Поискав готовые решения на сайте lua-users, я нашел подходящий код для сохранения таблиц в файл, и переписал его под работу со строкой. http://pastebin.com/AYB7u25g Код: -- ********************************************************************************** -- -- ** Serialize table to string ** -- -- ** ** -- -- ** Modified version of http://lua-users.org/wiki/SaveTableToFile ** -- -- ** By Krutoy242 ** -- -- ********************************************************************************** -- -- declare local variables --// exportstring( string ) --// returns a "Lua" portable version of the string local function exportstring( s ) return string.format("%q", s) end local insert = table.insert local tostring= tostring local ipairs = ipairs local pairs = pairs local type = type --// The Save Function function table.toString(tbl) if type(tbl) ~= 'table' then return "" end -- Argument not a table local charS,charE = " ","\n" local s_tbl = {} -- initiate variables for save procedure local tables,lookup = { tbl },{ [tbl] = 1 } insert(s_tbl, "return {"..charE ) for idx,t in ipairs( tables ) do insert(s_tbl, "-- Table: {"..idx.."}"..charE ) insert(s_tbl, "{"..charE ) local thandled = {} for i,v in ipairs( t ) do thandled = true local stype = type( v ) -- only handle value if stype == "table" then if not lookup[v] then insert( tables, v ) lookup[v] = #tables end insert(s_tbl, charS.."{"..lookup[v].."},"..charE ) elseif stype == "string" then insert(s_tbl, charS..exportstring( v )..","..charE ) elseif stype == "number" or stype == "boolean" then insert(s_tbl, charS..tostring( v )..","..charE ) end end for i,v in pairs( t ) do -- escape handled values if (not thandled) then local str = "" local stype = type( i ) -- handle index if stype == "table" then if not lookup then insert( tables,i ) lookup = #tables end str = charS.."[{"..lookup.."}]=" elseif stype == "string" then str = charS.."["..exportstring( i )..]=" elseif stype == "number" or stype == "boolean" then str = charS.."["..tostring( i )..]=" end if str ~= "" then stype = type( v ) -- handle value if stype == "table" then if not lookup[v] then insert( tables,v ) lookup[v] = #tables end insert(s_tbl, str.."{"..lookup[v].."},"..charE ) elseif stype == "string" then insert(s_tbl, str..exportstring( v )..","..charE ) elseif stype == "number" or stype == "boolean" then insert(s_tbl, str..tostring( v )..","..charE ) end end end end insert(s_tbl, "},"..charE ) end insert(s_tbl, "}" ) return table.concat(s_tbl) end --// The Load Function function table.fromString(s) if not s then return end -- Argument not string local ftables = loadstring(s) if not ftables then return end -- String cant be parsed into function local tables = ftables() for idx = 1,#tables do local tolinki = {} for i,v in pairs( tables[idx] ) do if type( v ) == "table" then tables[idx] = tables[v[1]] end if type( i ) == "table" and tables[i[1]] then insert( tolinki,{ i,tables[i[1]] } ) end end -- link indices for _,v in ipairs( tolinki ) do tables[idx][v[2]],tables[idx][v[1]] = tables[idx][v[1]],nil end end return tables[1] end Userdata, Функции и метотаблицы не сохраняются Сохраняются только простые значения как таблицы, строки, числа а так же true\false Замечу, что в моем коде для сбора строки используется таблица и метод table.concat(), который увеличивает скорость работы в разы. Код можно использовать как в CС так и в OС. Он добавляет новые методы в глобальную таблицу table и вызывается так: -- Таблица, которую мы превращаем в строку local obj = {[0]=1, 2, 3, ["fieldName"]=0, {6,7,8}}-- Сериализацияlocal s = table.toString(obj)-- Обратно из строки в таблицуlocal _obj = table.fromString(s) Результаты для двухмерного массива с 1 000 000 полей и замеры времени выполнения: //CC textutils serialize(): 45.94 unserialize(): 1.73 //OC serialization serialization.serialize(): 40.00 serialization.unserialize(): 0.87 //Krutoy table.tostring: table.toString(): 1.80 table.fromString(): 1.19 Пруф для меньшего количества полей: http://ideone.com/ICpS0L Изменено 16 апреля, 2015 пользователем Krutoy 4 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Totoro 3 563 Опубликовано: 16 апреля, 2015 (изменено) Полезно. Но ты сравнивал по производительности с библиотекой OC Serialization API? (https://github.com/MightyPirates/OpenComputers/blob/master-MC1.7.10/src/main/resources/assets/opencomputers/loot/OpenOS/lib/serialization.lua) Твой пример под OC: local serial = require('serialization') -- Таблица, которую мы превращаем в строку local obj = {[0]=1, 2, 3, ["fieldName"]=0, {6,7,8}} -- Сериализация local s = serial.serialize(obj) -- Обратно из строки в таблицу local _obj = serial.unserialize(s) Изменено 16 апреля, 2015 пользователем Totoro Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Zer0Galaxy 2 187 Опубликовано: 16 апреля, 2015 (изменено) Внутренние методы СС Textutils.serialize не подходили, из за медленного оператора ".." , который добавлял в итоговую строку символы. Поискав готовые решения на сайте lua-users, я нашел подходящий код для сохранения таблиц в файл, и переписал его под работу со строкой. Но ведь там же сплошь и рядом конкатенация. Ты сравнивал по производительности с serialize? Изменено 16 апреля, 2015 пользователем Zer0Galaxy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Krutoy Автор темы 1 169 Опубликовано: 16 апреля, 2015 Полезно. Но ты сравнивал по производительности с библиотекой OC Serialization API? (https://github.com/MightyPirates/OpenComputers/blob/master-MC1.7.10/src/main/resources/assets/opencomputers/loot/OpenOS/lib/serialization.lua) Нет, не сравнивал, но попробую сравнить позже. Быстрым просмотром кода я обнаружил что в ОС тоже используется оператор ".." к общей строке Но ведь там же сплошь и рядом конкатенация. Ты сравнивал по производительности с serialize? Производительность не сравнивал, доверился расчетам. Но могу и провести. Суть в том, что в моем коде осуществляется конкатенация коротких подстрок. В стандартных же либах СС и ОС производится добавление символов в общую строку, что намного медленнее. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Krutoy Автор темы 1 169 Опубликовано: 16 апреля, 2015 (изменено) Итак, я провел тесты. Результаты потрясающие - почти мой код сериализует в десятки раз быстрее. Для двухмерного массива с 1 000 000 полей замеры времени выполнения: //CC textutils serialize(): 45.94 unserialize(): 1.73 //OC serialization serialization.serialize(): 40.00 serialization.unserialize(): 0.87 //Krutoy table.tostring: table.toString(): 1.80 table.fromString(): 1.19 Пруф для меньшего количества полей: http://ideone.com/ICpS0L Изменено 16 апреля, 2015 пользователем Krutoy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
1Ridav 1 049 Опубликовано: 16 апреля, 2015 Итак, я провел тесты. Результаты потрясающие - почти мой код сериализует в десятки раз быстрее. Для двухмерного массива с 1 000 000 полей замеры времени выполнения: //CC textutils serialize(): 45.94 unserialize(): 1.73 //OC serialization serialization.serialize(): 40.00 serialization.unserialize(): 0.87 //Krutoy table.tostring: table.toString(): 1.80 table.fromString(): 1.19 Пруф для меньшего количества полей: http://ideone.com/ICpS0L Не забываем про КЭШ, он сильно искажает показатели тестов, поэтому его надо очищать Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Krutoy Автор темы 1 169 Опубликовано: 16 апреля, 2015 Не забываем про КЭШ, он сильно искажает показатели тестов, поэтому его надо очищат Нет Рид, не в этом случае. Если запускать отдельно каждую функцию результат идентичный. Пруф для 100 000: http://ideone.com/JZODo2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
1Ridav 1 049 Опубликовано: 16 апреля, 2015 Нет Рид, не в этом случае. Если запускать отдельно каждую функцию результат идентичный. Пруф для 100 000: http://ideone.com/JZODo2 После создания таблицы и её обработки - она попадает в кэш. Она может быть там часами, если её не заменит что либо другое. Так что единственный способ исключить это влияние - заполнять таблицу другими данными перед каждым тестом. Заполнил Сериализовал Заполнил Разсериализовал Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Krutoy Автор темы 1 169 Опубликовано: 16 апреля, 2015 (изменено) После создания таблицы и её обработки - она попадает в кэш. Она может быть там часами, если её не заменит что либо другое. Так что единственный способ исключить это влияние - заполнять таблицу другими данными перед каждым тестом. Заполнил Сериализовал Заполнил Разсериализовал Посмотри первые 30 строк пруфа где я собственно создаю и сериализую таблицу. Я оставил только 1 сериализацию и замер выдает идентичные результаты, даже при отдельном запуске каждого типа сериализации. Изменено 16 апреля, 2015 пользователем Krutoy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Artiom 0 Опубликовано: 8 августа, 2024 Шалом, я знаю что занимаюсь некропостингом, но всё же надеюсь на помощь. Я профан в lua OC и программировании в целом, я слегка понимаю что тут происходит, но пока только начинаю постигать сие ремесло. Скопировав данный код мне выдало 3 ошибки В 16.04.2015 в 12:54, Krutoy сказал: str = charS.."["..exportstring( i )..]=" elseif stype == "number" or stype == "boolean" then str = charS.."["..tostring( i )..]=" первые 2 были здесь, я вроде справился поставив " перед ]=. 3 же ошибка настигла меня при попытке вызова table.fromString() В 16.04.2015 в 12:54, Krutoy сказал: local ftables = loadstring(s) как я понял функции loadstring() почему то нету. Её надо заменить на какую то другую или подгрузить библиотеку? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 155 Опубликовано: 8 августа, 2024 27 минут назад, Artiom сказал: первые 2 были здесь, я вроде справился поставив " перед ]=. 3 же ошибка настигла меня при попытке вызова table.fromString() А что за ошибки были, и что за ошибка сейчас? 28 минут назад, Artiom сказал: str = charS.."["..exportstring( i )..]=" elseif stype == "number" or stype == "boolean" then str = charS.."["..tostring( i )..]=" В глаза бросается отсутствие открывающих кавычек в двух фрагментах кода ]=". Я бы ожидал увидеть "]=". 32 минуты назад, Artiom сказал: как я понял функции loadstring() почему то нету. В OpenComputers, насколько я помню, нет функции loadstring(), но есть load(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Artiom 0 Опубликовано: 8 августа, 2024 (изменено) 46 минут назад, eu_tomat сказал: Я бы ожидал увидеть "]=". Ну я собственно это я и сделал, 1 и 2 ошибки были при запуске файла "unexpected symbol near ']' ", 3 уже в интерпретаторе lua при обращении к функции table.fromString() примерно:"попытка индексировать переменную со значение nil (глобальная loadstring)" 46 минут назад, eu_tomat сказал: В OpenComputers, насколько я помню, нет функции loadstring(), но есть load(). я поменял ошибки больше нет, спасибо. Но появилась новая проблема таблицы-массивы (на скрине tb1) обрабатывает нормально, а вот таблицы с ключами (tb) он превращает в пустые таблицы, заменой ipairs на pairs это отчасти решилось. Но эта библиотека разве не должна передавать ключи? У меня она их игнорирует и делает из таблицы с ключами массив( Изменено 8 августа, 2024 пользователем Artiom Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 155 Опубликовано: 8 августа, 2024 2 часа назад, Artiom сказал: Но эта библиотека разве не должна передавать ключи? Кто же её знает, что она должна? Тут надо автора пингануть. Возможно он услышит нас. @Krutoy Если не трудно, расскажи, как должна твоя библиотека работать с таблицами. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах