2015-08-07 1 views
1

Я открыл этот вопрос на GitHub проекта Prevayler-CLJРазмер Java сериализовать структуры данных Clojure

https://github.com/klauswuestefeld/prevayler-clj/issues/1

потому 1M короткие векторы, как этот [:a1 1], образуя состояние Prevayler, приводит к размеру файла 1 Гб при последовательном сериализации, один за другим, с Java writeObject.

Возможно ли это? Около 1 кБ для каждого PersistentVector? Дальнейшие исследования показали, что такое же количество векторов можно сериализовать в файле размером 80 МБ. Итак, что происходит неправильно в сериализации превалитера? Я делаю что-то неправильно в этих тестах. Пожалуйста, обратитесь к проблеме github для моих отрывков кода теста.

+0

Да. Речь идет о размерах Java-сериализованных структур данных Clojure. Может ли вектор с двумя элементами быть размером 1 КБ? Почему сериализация в моем эксперименте REPL (см. Код, следующий за соответствующей ссылкой) создает буфер размером 80 Мбайт, тогда как журналы предварительного просмотра составляют 1 ГБ? – icamts

+0

Моя гипотеза. Является ли переопределяющим определение класса prevayler каждый раз? Если это так, почему это происходит? Мое понимание кодекса prevayler предполагает, что он должен иметь такое же поведение в моем экспериментальном коде. – icamts

+1

Я вижу сейчас. Он тщательно изучил контент из внешнего ресурса (у SO есть разные стандарты, чем вы можете использовать). Таким образом, preayler может конкатенировать выходные данные независимых объектов ObjectOutputStream. Я вижу, как это может возникнуть в архитектуре FP-esque. –

ответ

1

Prevayler по-видимому, начинает свежий ObjectOutputStream для каждого сериализованного элемента, предотвращая повторное использование класса данные между ними. С другой стороны, ваш тестовый код написан «естественным» способом, позволяющим повторное использование. Какие силы Prevayler перезапускать каждый раз не ясны для меня, но я бы стеснялся назвать его «особенностью», учитывая его негативное влияние; «обходной путь» - более вероятное обозначение.

+0

Просто для полноты Клаус объяснил, что это утечки памяти, которые он хочет предотвратить.Экземпляр OOS содержит ссылки на транзакции, препятствующие их сбору. Он говорит, что вызов сброса каждые 100 транзакций будет хорошим компромиссом между размером памяти и размером файлов журналов. – icamts

1

Нет ничего плохого в отношении prevLayer за один вопрос. Это просто, что метод writeObject java не совсем настроен на запись данных clojure; он предназначен для хранения внутренней структуры любого сериализуемого Java-объекта. Поскольку векторы clojure являются достаточно сложными java-объектами под капотом, я не очень удивлен тем, что маленький вектор может выписать примерно как килограмм данных.

Я бы предположил, что почти любой метод сериализации, специфичный для clojure, приведет к уменьшению файлов. По опыту стандарт clojure.core/pr + clojure.core/read дает хороший баланс между размером файла и скоростью и обрабатывает структуры данных практически любого размера.

Смотрите эти страницы для некоторого понимания в внутренностях Clojure векторов:

+1

1. Предполагается, что базовый класс контейнера, такой как 'PersistentVector', будет иметь оптимизированный двоичный формат для стандартной сериализации Java. 2. OP указывает, что prevayler может использовать сериализацию Java неправильно, сериализуя каждый вектор в независимый ObjectOutputStream, а затем объединяет их. Это предотвращает повторное использование определений классов. –

+0

@JoostDiepenmaat Спасибо за ваш ответ. – icamts

+0

@MarkoTopolnik Спасибо за ваши подсказки. Я нашел разницу между моими тестами и кодом prevayler. Prevayer вызывает '(.reset obj-out)' в строке 42. Таким образом, он использует тот же 'ObjectOutputStream', но в результате он сериализует определения классов для каждой записи. Клаус (автор автора) считает, что это не ошибка, а функция предотвращения утечек. Если вы переписываете свои комментарии в ответе, я буду рад принять его. – icamts