Перейти к содержимому
RccHD

Библиотека для работы с бинарными данными в Lua

Рекомендуемые сообщения

Совсем недавно я выложил свою библиотеку, которая позволяет экономить оперативную память при хранении бинарных данных.
Из фатальных недостатков той старой библиотеки можно выделить:
1) Колоссальная нагрузка на CPU и сборщик мусора
2) Работа со иммутабельными строками

Получив порцию критики, я переписал библиотеку и добился офигенных результатов.
Новая библиотека экономит ровно столько же оперативки ( экономия до 80-90% ) и при этом не имеет перечисленных недостатков старой.

 


UniDataArray.lua

Примечание: для работы с этой библиотекой необходимо наличие следующий библиотек:
1) num_transform.lua
2) class.lua (доработанная версия)

Новая библиотека сильно отличается от старой версии. Теперь вместо строк используется таблица с числами. Интерфейс взаимодействия с UniDataArray реализован так, что при каждой операции записи-чтения данных происходит изменение внутреннего содержимого таблицы с числами.

В Lua используются 64-битные числа, что дает возможность использовать их как хранилище более мелких "частичек информации". Например, одно число в Lua может хранить информацию о 8 байтах или о 64 битах.


Работа библиотеки основана как раз на этой возможности умещать данные в больших числах.

Вот пример использования библиотеки UniDataArray.lua

 









-- ФУНКЦИЯ КРАСИВОЙ ОТРИСОВКИ
-- К библиотеке отношения не имеет
local pprint = function(v, t)
    print("\27[32m"..tostring(v or "").."\27[37m")
    io.write("-> ")
    if type(t) == "table"
    then for k, v in pairs(t) do io.write(tostring(v).." ") end
    else io.write(tostring(t)) end
    print("\n------------------------------------")
end
local UniDataArray = require("UniDataArray")
-- создание массива размером 20 с разрядностью = 256. (массив байт)
-- т.е. 20 байтlocal
array = UniDataArray(20, 256)
-- числа...
local numbers = {1,0,234,22,12,99,44,3,121,200}
-- позиция курсора
local position = 0
-- запись чисел numbers в массив array начиная с позиции position
position = array.write(position, numbers)
--- ВЫВОД ИНФОРМАЦИИ НА ЭКРАН :
-----------------------------------------
print("\n\n")----------------------------
-----------------------------------------
pprint("Кусок из 5 байт (с 2 по 6)"
	   ,array.read(1, 5)			          )
pprint("Исходные данные (каждое число -- это отдельный блок) "
	   ,array.data					  )
pprint("Количество блоков"
	   ,array.length				  )
pprint("Размер блока "
	   ,array.block_len				  )
pprint("Общее кол-во отдельных элементов"
	   ,array.block_len * array.length                )
pprint("Позиция курсора"
	   ,position					  )
pprint("Первый блок "	   ,array.internal.getBlock(1)	  )
pprint("Второй блок "	   ,array.internal.getBlock(2)	  )
-----------------------------------------
print("\n\n")----------------------------
-----------------------------------------

Вот такой текст мы увидим на экране:

wn3OvVe.png

Мы видим, что первое число в "исходных данных" равняется 1103438941283
Это число имеет такое большое значение, потому что оно хранит байты {1, 1, 234, 22, 12, 99} (см. "Первый блок")
Каждое число в "исходных данных" является блоком, в котором хранятся числа в определенной системе счисления ( в данном случае система счисления = 256 )

Все аналогично и для второго блока, для третьего и так далее...



Абзац с неинтересным описанием некоторых интересных моментов:
При создании массива данных в кодировке base размера N программа создаст ровно столько блоков, сколько необходимо для хранения N чисел.
Чем больше значение кодировки, тем меньше чисел этой кодировки может поместиться в блок.
При создании массива байт каждый блок будет вмещать 6-7 ячеек.

local arr = UniDataArray(100000, 256) -- кодировка 256, значит это байты
print(arr.block_len) -- длина блока = 6 ячеек
print(arr.length) -- всего создано 16667 блоков

Но вот при создании массива бит, каждый блок будет иметь аж 62 ячейки:



local arr = UniDataArray(100000, 2) -- кодировка 2, значит это биты
print(arr.block_len) -- длина блока равна 62 ячейкам
print(arr.length) -- всего создано 1613 блоков

Также есть возможность создания массивов в кодировках 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, но кому оно надо, я не знаю :)
Реализовал "чтобы было". Лично я пользуюсь только кодировками 2 и 256.

Каждый блок занимает примерно 64 бита вне зависимости от количества ячеек в нем






Краткая документация библиотеки

 

 

Чтобы создать UniData-массив нужно вызвать функцию-конструктор передав в нее два аргумента:
1) необходимое количество ячеек
и
2)допустимую кодировку этих ячеек. Пример:

local UniDataArray = require("UniDataArray")
local array = UniDataArray(100000, 4) -- создание массива из 100000 'четырехразрядных' чисел

У класса UniDataArray есть следующие методы:
write = function(pos, bytes) -- записывает числа bytes
(table) начиная с позиции pos(number). Возвращает позицию последней записанной ячейки
read = function(pos, count) -- считывает count
(number) чисел начиная с позиции pos(number).
Возвращает позицию последней прочитанной ячейки
fill = function(elem) -- устанавливает значение elem(number) всем ячейкам в массиве








Пример использования UniDataArray как массива битов

Ну, в этом нет ничего сложного:

local UniDataArray = require("UniDataArray")
local array = UniDataArray(20, 2) -- массив из 20 битов
array.write(0, {0, 1, 0, 1, 1, 1, 0}) -- записать биты 0101110 в ячейки после нулевой. 0
array.write(5, {1, 1, 1, 1, 0, 1, 1}) -- записать биты 1111011 в ячейки после пятой.  5
local someData = array.read(2, 5) -- прочитать 5 битов начиная с позиции 2
print(table.unpack( someData )) -- выведет на экран 01111



Ну и на сладкое у нас тест производительности!
Table VS UniDataArray

Запускал на тех же тестах, что и в прошлый раз.


 






local bytearray = require("UniDataArray")
local computer = require("computer")
local freeMem = function() -- возвращает усредненное значение computer.freeMemory()
    local m = 0
    for i = 1, 20 do m = m + computer.freeMemory() os.sleep(0.2) end
    return m / 20
end
-- ТЕСТ 1 (UniDataArray)
local mem1 = freeMem()
local array = UniDataArray(100000, 256) -- массив 100000 байт
array.write(3, {1, 2, 3, 4, 5, 6, 7, 8, 9})
local mem2 = freeMem()
print("Потрачено оперативки массивом байт(UniDataArray): "..tostring(mem1 - mem2))

print("\n\n\n")

-- ТЕСТ 2 (table)
local mem1 = freeMem()
local array = {}; for i = 1, 100000 do array[i] = 0 end -- массив 100000 байт
for i = 1, 9 do array[i + 3] = i end
local mem2 = freeMem()
print("Потрачено оперативки таблицой(table): "..tostring(mem1 - mem2))

 


Результат теста:
HYdBHTf.png



Плюсы библиотеки:
описаны выше( потребление оперативки сокращается в 20, мать его, раз! )
Минусы: библиотека пока еще очень сырая, но это поправимо. Я ее еще успею отполировать ;)

Изменено пользователем RccHD

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Я писал эту чертову программу весь день, но зато узнал много нового

 

Я уверен, применений у этой библиотеки огромное количество, так как в опенкомпах всегда не хватает оперативки(в сложных графонистых системах).

Никто ведь не будет отказываться от 20-кратного уменьшения потребления оперативной памяти игрушечного компа

 

:)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Интересно, работает ли либа на Lua 5.2? Возможный диапазон целых чисел на прошлой версии отличается от 5.3:

 

Sz80cV2.png?1

 

bwB1BHl.png?1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Интересно, работает ли либа на Lua 5.2? Возможный диапазон целых чисел на прошлой версии отличается от 5.3:

 

Sz80cV2.png?1

 

bwB1BHl.png?1

Если что-то перестанет работать, изменю в коде либы число '64' на '32' или добавлю проверку на версию Lua

Изменено пользователем RccHD

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Черт, я кажется скинул забаглванную версию. При работе с шестнадцатиричными числами происходит какая-то неведомая магия. Сейчас буду править код

 

Пока не спешите использовать эту либу в каком-то серьезном проекте. Эта либа будет считаться 'проверенной' после того, как часть операционки я напишу на UniDataArray. Пока что нестабильно работает

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Все пофиксил и потестил. Работает стабильно ( вроде бы )

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Объясните дураку, как скачать библиотеку? Я потратил 15 минут и не нашел в четырежды просмотренном посте ссылку на саму либу, только на зависимости. И такое почти во всех темах с библиотеками. ГДЕ ОНИ ХРАНЯТСЯ? ОТКУДА ИХ КАЧАТЬ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Объясните дураку, как скачать библиотеку? Я потратил 15 минут и не нашел в четырежды просмотренном посте ссылку на саму либу, только на зависимости. И такое почти во всех темах с библиотеками. ГДЕ ОНИ ХРАНЯТСЯ? ОТКУДА ИХ КАЧАТЬ?

А это кто-то из админов доигрался с шаблонами. Так, что теперь они все потёрлись. А в них была инфа, включая ссылку на либу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@@Fingercomp а что за библиотеки? какие шаблоны? что именно потерлось? у кого?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В начале поста был список с инфой всякой про библиотеку.

 

Название: бла-бла

Версия: 1.4.2

Скачать: ссылка

...и так далее. Вот такая штука.

 

Значения для них ставились в специальных полях, отдельно от самого сообщения. И темы по шаблону создавались тоже: сначала инфа, потом само сообщение. А сейчас всё это внезапно исчезло, так как шаблон удалён был.

 

Я полагаю, Кибер знать больше должен здесь.

Изменено пользователем Fingercomp

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Прошу прощения, что занимаюсь некропостингом. Уж не знаю, пригодится ли эта библиотека кому-нибудь, но ссылку на нее я нашел.

Можете переходить, смотреть.

Pastebin: UniDataArray

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в тему...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


×
×
  • Создать...