Как сериализовать и загрузить объект в SBCL/Common Lisp

У меня есть объект o, который является экземпляром класса X в SBCL.

Мне нужна функция write-X-object, которая сериализует o в файл таким образом, что когда этот файл считывается обратно с помощью load-X-object, результирующий объект эквивалентен o.

;; writing the object
(write-X-object o "~/tmp/o.serialized")

;; reading the object, much later, 
;; after sbcl has been exited and restarted

(setq v (read-X-object "~/tmp/o.serialized"))

o может иметь размер около гигабайта (или массив из нескольких миллионов более мелких объектов) со сложной структурой, поэтому идея состоит в том, чтобы чтение и запись выполнялись как можно быстрее.


person kdog    schedule 18.09.2016    source источник
comment
Посетите github.com/conspack/cl-conspack.   -  person PuercoPop    schedule 18.09.2016


Ответы (2)


Есть три основных способа сделать это

  1. Используйте встроенные средства печати/чтения: вы можете определить метод для print-object для вашего класса, который будет его сериализовать (возможно, вам нужно, чтобы он зависел от какой-то специальной переменной, чтобы вы не печатали гигабайты в repl). Затем вы можете определить макрос чтения (соответствующий любому синтаксису, который вы используете для печати вашего объекта), затем, чтобы сохранить свой объект, вы должны сделать (with-open-file (x "/tmp/foo" :direction :output) (print my-object X)), а чтобы вернуть его, вы должны сделать (with-open-file (x "/tmp/foo") (read x). Плюсы в том, что это просто. Минусы в том, что это медленно и не эффективно.
  2. Вы можете воспользоваться сторонней библиотекой сериализации, такой как conspack, которую предложил комментатор. Плюсы: достаточно быстро читать или писать. Минусы: вы не можете инкрементно прочитать объект больше, чем память.
  3. Вы можете реструктурировать свой класс (используя MOP), чтобы объект можно было хранить в памяти и на диске в том же формате, а затем использовать mmap для его чтения/записи. Примером библиотеки для этого является manardb. Эта система также позволяет хранить множество различных объектов. Плюсы: нет накладных расходов на чтение/запись на/с диска. Может автоматически обрабатывать объекты, размер которых больше, чем основная память (это обрабатывает загрузку/выгрузку оперативной памяти для вас). Минусы: могут быть небольшие накладные расходы для доступа к полям объекта. Обратите внимание, что с помощью этого метода обычно можно избежать большинства недостатков, используя реализацию, которая может правильно оптимизировать доступ через указатели ffi и используя специализированные структуры данных (например, массив с плавающей запятой намного лучше, чем общий массив)
person Dan Robertson    schedule 18.09.2016
comment
Спасибо. Просто чтобы внести ясность, я стараюсь избегать варианта 1 по нескольким причинам: он медленный, неэффективно использует пространство и усложняет кодирование. Я рассмотрю вариант 2. - person kdog; 18.09.2016
comment
Это поздно, но вариант 1 может быть достаточно эффективным, если файл сжат (хотя это может быть медленным), хотя у него есть и другие недостатки. - person Dan Robertson; 24.04.2019

например, определить метод print-object, я думаю, вы можете переопределить общую функцию MAKE-LOAD-FORM на defmethod.

создать-загрузить-форму и make-load-form-saving-slots определены в HyperSpec.

Они возвращают две формы, затем вы можете записать форму в файл с текстом, хотя это может занять больше места на диске (сравните запись конкретной двоичной спецификации).


А на CLiki есть страница о сериализации. Я думаю, что сейчас будет работать какой-то сторонний пакет.

person lagagain    schedule 20.04.2019