Как стать автором
Обновить

Комментарии 67

НЛО прилетело и опубликовало эту надпись здесь
Нет, эту библиотеку не рассматривали.
Отбирали только библиотеки, позволяющие локально в самой JVM выполнять сериализацию/десериализацию произвольных java Object-ов, без знания схемы/структуры их данных.
Чем обусловлено использование openJ9? Вы используете только эту jvm?
Выбор IBM J9 VM 1.7.0 обусловлен историческими причинами. Мы были вынуждены «научиться жить» в таком runtime окружении и делать это максимально быстро. Планы использовать другие JVM есть, как у всех перспективных продуктов :) В следующих публикациях я постараюсь выполнить сравнительный анализ на разных JVM.
Спасибо за подробную статью! Было приятно увидеть one-nio в топе.

Хочу отметить, что компактный вариант сериализации изначально задумывался для быстрого RPC с поддержкой эволюции классов. При этом не требуется передавать схемы вручную: главная фишка one-nio — в динамическом обмене схемами между клиентом и сервером. Это работает из коробки в RpcClient/RpcServer из той же библиотеки.

Хотел узнать, почему в таблице отмечена невозможность десериализовать классы, отсутствующие в classpath? Для отсутствующих классов one-nio автоматически генерирует классы-заглушки, и это неотъемлемая часть процедуры обмена схемами.
Динамический обмен схемами в One Nio мы видели и, честно говоря, впечатлились. Я попытался отразить суть этой процедуры в разделе «Гибкость», когда говорил про одновременное использование достоинств One Nio (скорость) и One Nio (for persist) (гибкость). Из коробки RpcClient/RpcServer «as is» нам не подошли из-за нашей специфики, поэтому мы делаем обмен схемами немного по-своему.

На счёт генерируемых заглушек при десериализации классов, отсутствующих в classpath. Действительно, эта любопытная механика заслуживает галочки в таблице раздела «Гибкость» — скорректирую. Спасибо за наводку, изначально я не разглядел всю прелесть этой фичи.
. Для того чтобы объективно оценить, какая из библиотек сериализации быстрее, мы взяли реальные данные из логов нашей системы и скомпоновали из них синтетические сессионные данные разной длины: от 0 до 1 МБ


А можно глянуть на примеры данных для теста «Десериализация до 1КБ»? Кроме того, непонятно, в какие структуры это все десериализовалось. Хотелось бы и на исходники микробенчмарков глянуть.

PS: Сразу приношу извинения, если это есть в статье, а я пропустил :)
Боюсь, что примеры данных показать не могу, т.к. это результаты сериализации реальных данных из логов системы, а сериализация — это обратимый процесс.

Структура сериализуемых/десериализуемых данных при «Гонках» и «Взвешивании» была примерно следующая:
  • объекты, вложенные друг в друга до 3-его уровня
  • помимо других объектов, в каждом объекте присутствовали поля с типами String, Long, Map, byte[]

Микробенчмарки тривиальные:
  • в @Setup-методе готовим сериализатор, объект для сериализации и byte[] с результатами сериализации (для benchmark-а десериализации)
  • далее в самих @Benchmark-ах просто выполняем serialize/deserialze

Спасибо за интересное сравнение. А вы не сравнивали, например, топ-5 участников с тем же protobuf-ом? Если выходит, что последний не дает никаких плюсов, то зачем с ним мучиться(встречал конторы где protobuf как укроп, пихали везде, даже во фронт).

protobuf позволяет данные в не гомогенной среде передавать. One Nio и другие только с Java работают.

Это все понятно, зачастую работа с jvm и нужна, KISS. Но вот есть, некоторые, у кого руки чешутся прикрутить protobuf где ненужно(payload сообщений в PubSub, например), а то что он без дела в джаве только шуршит.

Зачастую лучший инструмент это тот, который лучше знаешь.
Затраты на изучение и применение другого инструмента редко окупаются.
Protobuf отсеяли сразу, т.к. у нас, в принципе, нет схем сериализуемых данных. Не стали создавать «Франкенштейна», притягивая за уши Protobuf.
есть ли шанс увидеть тестирование более широкого круга (например, +Gson) и на HotSpot?
кстати, где можно посмотреть сами тесты и json'ы?
Как уже писал, в следующих публикациях я постараюсь выполнить сравнительный анализ на разных JVM. Более широкий круг сериализаторов?.. Возможно, если обнаружатся достаточно быстрые аналоги.

Описание @Benchmark-ов и сериализуемых объектов привёл выше. БОльшая часть «участников соревнования» используют бинарный формат, а не JSON.
если интересны бенчмарки сериализаторов в json, то можно посмотреть тут github.com/wizzardo/json-benchmarks
спасибочки!
А исходный код бенчмарков — коммерческая тайна? Было бы интересно:
  • прогнать на оборудовании, похожем на клиентское :)
  • сравнить с рукопашной упаковкой в byte[], поскольку конкретно у меня — есть всего с десяток классов, которые нужно держать в памяти и сбрасывать на диск, но суммарно может быть под миллиард экземпляров
  • проверить, не окажется ли выгоднее хранить в JVM бинарные представления для объектов с десериализацией при обращении «по требованию», нежели честные экземпляры классов
  • проверить на объектах размером в 20, 40 и 80К, поскольку, к сожалению, таковые вполне могут случиться
Описание @Benchmark-ов и сериализуемых объектов привёл выше.
Используемые для сериализации данные, боюсь, что показать не могу, т.к. это реальные данные из логов системы.
При увеличении размера сериализуемых объектов до 1 МБ кривые на графиках скорости предсказуемо расходятся практически по прямым линиям. Победители и аутсайдеры видны уже, начиная с 10 КБ.

В целом, сериализация Java объектов может быть применима для большого круга задач, была бы фантазия. Но конкретный profit нужно мерить.
Жалко как. Было бы очень полезно, если выложили бы код бенчмарков без данных из реальных логов системы. А то получается как в маркетинговах статьях на примере IMDG: Hazelcast быстрее Ignite(и наоборот) в N раз, но код мы вам показывать не будем, а воспроизвести не получается.

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

Исходники бенчмарков постараюсь к следующей публикации разместить на Github-е.
Пока могу показать лишь «скелет» без деталей реализации:
JMH-бенчмарк без деталей
public class SerializationPerformanceBenchmark {

    @State( Scope.Benchmark )
    public static class Parameters {

        @Param( {
            "Java standard",
            "Jackson default",
            "Jackson system",
            "JacksonSmile default",
            "JacksonSmile system",
            "Bson4Jackson default",
            "Bson4Jackson system",
            "Bson MongoDb",
            "Kryo default",
            "Kryo unsafe",
            "FST default",
            "FST unsafe",
            "One-Nio default",
            "One-Nio for persist"
        } )
        public String serializer;
        public Serializer serializerInstance;

        @Param( { "0", "100", "200", "300", /*... */ "1000000" } )  // Toward 1 MB
        public int sizeOfDto;
        public Object dtoInstance;
        public byte[] serializedDto;

        @Setup( Level.Trial )
        public void setup() throws IOException {
            serializerInstance = Serializers.getMap().get( serializer );
            dtoInstance = DtoFactory.createWorkflowDto( sizeOfDto );
            serializedDto = serializerInstance.serialize( dtoInstance );
        }

        @TearDown( Level.Trial )
        public void tearDown() {
            serializerInstance = null;
            dtoInstance = null;
            serializedDto = null;
        }
    }

    @Benchmark
    public byte[] serialization( Parameters parameters ) throws IOException {
        return parameters.serializerInstance.serialize(
                parameters.dtoInstance );
    }

    @Benchmark
    public Object unserialization( Parameters parameters ) throws IOException, ClassNotFoundException {
        return parameters.serializerInstance.deserialize(
                parameters.serializedDto,
                parameters.dtoInstance.getClass() );
    }
}

За абстракцицей Serializer скрыты все 14 исследуемых реализаций Java-сериализаторов.

Конфигурация jackson во всех вариациях была дефолтной? Т.е. ObjectMapper без подключения модуля Afterburner и с дефолтным LRUMap в ObjectMapper->typeFactory->typeCache?

Конфигурации Jackson-а приведены в spoiler-е для 3-его участника — Jackson JSON (with types). Возможности тюнинга нам были бы интересны.
Попробуйте включить afterburner и во все классы данных для сериализации/десериализации добавить геттеры и сеттеры, т.к. инъекция данных в поля через рефлексию — дорогостоящая операция. Ну и кэш потюнить, если количество типов, проходящих через ObjectMapper >= 100.
Потюнить Jackson, конечно, интересно, и я постараюсь это сделать, как будет время. Спасибо за наводки.
Однако добавлять геттеры и сеттеры в сериализуемые объекты — это не то, что нам нужно: объекты готовят потребители нашего сервиса, а мы должны быстро сериализовывать всё подряд.
Как я написал во введении, нам нужна библиотека, «не задающая лишних вопросов».
Наколеночный тест говорит, что afterburner дает грубо от 3% до 7% прироста производительности при десериализации и от 5% до 6% при сериализации. Зависит от размера данных.
Benchmarks
# JMH version: 1.23
# VM version: JDK 11.0.5, OpenJDK 64-Bit Server VM, 11.0.5+10
Benchmark (fileName) Mode Cnt Score Error Units
JacksonDeserialization.afterburnerModule request.json thrpt 719475.022 ops/s
JacksonDeserialization.afterburnerModule user.json thrpt 24939.785 ops/s
JacksonDeserialization.afterburnerModule repos.json thrpt 985.490 ops/s
JacksonDeserialization.afterburnerModule cities.json thrpt 57.935 ops/s
JacksonDeserialization.blackbirdModule request.json thrpt 718768.416 ops/s
JacksonDeserialization.blackbirdModule user.json thrpt 20479.817 ops/s
JacksonDeserialization.blackbirdModule repos.json thrpt 815.607 ops/s
JacksonDeserialization.blackbirdModule cities.json thrpt 56.831 ops/s
JacksonDeserialization.defaultMapper request.json thrpt 669093.374 ops/s
JacksonDeserialization.defaultMapper user.json thrpt 22144.445 ops/s
JacksonDeserialization.defaultMapper repos.json thrpt 780.062 ops/s
JacksonDeserialization.defaultMapper cities.json thrpt 55.894 ops/s
JacksonSerialization.afterburnerModule request.json thrpt 1207945.981 ops/s
JacksonSerialization.afterburnerModule user.json thrpt 131274.019 ops/s
JacksonSerialization.afterburnerModule repos.json thrpt 1368.781 ops/s
JacksonSerialization.afterburnerModule cities.json thrpt 59.140 ops/s
JacksonSerialization.blackbirdModule request.json thrpt 1216882.119 ops/s
JacksonSerialization.blackbirdModule user.json thrpt 122842.650 ops/s
JacksonSerialization.blackbirdModule repos.json thrpt 1204.178 ops/s
JacksonSerialization.blackbirdModule cities.json thrpt 56.534 ops/s
JacksonSerialization.defaultMapper request.json thrpt 1214062.085 ops/s
JacksonSerialization.defaultMapper user.json thrpt 123109.757 ops/s
JacksonSerialization.defaultMapper repos.json thrpt 1165.919 ops/s
JacksonSerialization.defaultMapper cities.json thrpt 55.973 ops/s


Похоже на правду?

ps данные и модели взяты тут
хм, странно, у нас на проекте он дал ~+30%-50% прироста при профилировке в операциях сериализации/десериализации на различных REST-хэндлерах по результатам нагрузочных стрельб Яндекс.Танком. Правда, у нас DTO были иммутабельными, проект собирался с ключом «javac -parameters», и ObjectMapper инициализировался с подключенным «jackson-module-parameter-names».
а какой кэш посоветуете?
Такой, например. Дефолтный сбрасывает полностью данные после 100 накопленных записей, причем дефолтный кэш — статичный и шарится между всеми инстансами ObjectMapper
Используя эту мета-информацию при десериализации, библиотека One Nio точно знает, как выглядел класс сериализуемого объекта на момент сериализации. Именно на основании этого знания алгоритм десериализации One Nio является таким гибким, что обеспечивает максимальную совместимость получающихся при сериализации byte[].

Это будет работать при условии полного совпадения классов в сервисе-источнике и сервисе-получателе? А если они различаются, тогда десериализация завершится с ошибкой, без возможности восстановления?

Нет, это будет работать при достаточно обширном наборе различий в классах источника и получателя. В этом и состоит гибкость.
Например, у отправителя появились новые поля в классе — более старый получатель просто их проигнорирует. У получателя появились новые поля — при получении данных от более старого отправителя новые поля останутся null-ами, либо значениями по умолчанию. Данных примеров с отличиями в классах отправителя и получателя масса.
Обратите внимание на столбик One Nio (for persist) в таблице раздела «Гибкость». Почти по каждому критерию-сценарию там зачтённый бал.

Одинаковое имя поля, но разного типа, п.8 — не поддерживает. И, если я правильно понял, нет возможности добавить метод конверсии для типов, не имеющих родственных связей.

Такое поддерживает только One Nio (for persist) и только в оригинальном виде с использованием sun.reflect.MagicAccessorImpl. Об этом написано в сноске #4 под таблицей раздела «Гибкость».
И да, у других библиотек не удалось найти даже custom-изируемых средств достижения данного свойства.
Мне кажется, что проблема не только в том, что нет кастомной конверсии, но и в том, что сама попытка конверсии должна быть опциональной. Поле имеет несколько атрибутов — владельца, порядковый номер, тип и имя. Почему-то если имя не совпадает, то поле останется null, а если тип не совпадает, то это критическая ошибка.
Если честно, то мне сложно представить case-ы, когда реально, а не надуманно, было бы необходимо поддержать смену типа у поля при развитии класса. Если меняется тип поля, то, вероятнее всего, это уже другое поле.

Почему-то если имя не совпадает, то поле останется null, а если тип не совпадает, то это критическая ошибка.
Потому что имя — это всего лишь строка, а тип определяет структуру данных. Смена типа — гораздо более серьёзное изменение, нежели смена имени поля.
Если меняется тип поля, то, вероятнее всего, это уже другое поле.

Так и я про то же. Почему при различии в типе поля нужно обязательно пытаться туда записать значение? Почему не просто проигнорировать поля с неподходящими типами?

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

А мы всё ещё говорим про мультисервисную архитектуру и сессионные данные в ней? Я вполне могу представить ситуацию, когда один не слишком аккуратно написанный сервис положил в сессию данные одного типа, а другой сервис попытался их прочитать в другой тип и упал.

С почином на Хабре. А вот код с бенчмарками на каком-нибудь GitHub'е не помешал бы. Народ это любит. Может получится к следующей публикации подготовить?
Спасибо!
Думаю, может получиться. Подумаю, как лучше сделать, и обязательно учту это пожелание.
У нас всё по-честному :)
Простите, а взять любой серьезный тест на скорость java json сериализаторов, найти там топ5 и дальше уже тестить их в ваших условиях правда очень сложно? Надо обязательно брать непойми что и сравнивать непойми как?
Исходников с повторяемыми результатами нет, значит сравнение сделано черти как. Кэп.

пример подобного теста
Судя по вашему уровню погруженности в тему, вы могли бы сами опубликовать отличный пост. Дерзайте!
Я пишу совершенно очевидные и тривиальные вещи:
Пользуйтесь опенсорс софтом для своей выгоды.
Открывайте исходники тестов.
Тесты должны быть повторяемы.

Писать статью о правилах проведения экпериментов? Так они уже написанны. О пользе опенсорса? Так тоже миллон уже.
Обидно что о Caucho Hessian уже даже не вспоминают. Я пробовал пару лет назад — получалось компактное представление, без схем и с возможностью кастомизации представления.
У FST есть аннотация Version

Add fields to classes without breaking compatibility to streams written with prior versions. See javadoc of the Version annotation and related test cases.

Warning versioning enables newer code to read objects written by an older version, not vice versa.
Да, мы смотрели в эту сторону, но предложенный способ использования аннотации @Version не подходит для нашей задачи, когда классы сериализуемых объектов готовятся потребителями нашего сервиса, а для самого сервиса это «чёрный ящик».
Кусок javadoc-а для аннотации @Version из FST
/**
 * support for adding fields without breaking compatibility to old streams.
 * For each release of your app increment the version value. No Version annotation means version=0.
 * Note that each added field needs to be annotated.
 *
 * e.g.
 *
 * class MyClass implements Serializable {
 *
 *     // fields on initial release 1.0
 *     int x;
 *     String y;
 *
 *     // fields added with release 1.5
 *     @Version(1) String added;
 *     @Version(1) String alsoAdded;
 *
 *     // fields added with release 2.0
 *     @Version(2) String addedv2;
 *     @Version(2) String alsoAddedv2;
 *
 * }

Как видим, нашим потребителям пришлось бы «заморочиться» со своими классами, сохраняемыми в сессию. А ведь из-за цепочек зависимостей объектов потребитель может даже не осознавать, что объекты какого-то из классов он сохраняет в сессию…
Таким образом, по умолчанию («не задавая лишних вопросов») у FST нет обратной совместимости со старыми сериализуемыми классами.
Не спорю. Для нас в своё время киллер-фичей FST послужила
up to 10 times faster 100% JDK Serialization compatible drop-in replacement
У One Nio те же плюсы, за одним непринципиальным исключением:
There is limited support for readObject/writeObject. These methods will be called, but they should not work with the stream directly. The only stream methods they may call are defaultReadObject and defaultWriteObject. Other calls will result in exception.

Externalizable is completely supported.
Сейчас, я бы FST не выбрал уже. Автор маленько подзабросил его. Issues на GitHub забиты просьбами поддержать 11,12 и т.п.
В 2016-ом выбор был не столь очевиден :)
Было бы интересно услышать/увидеть про тестирование сериализации от jboss:
serialization.jboss.org

В отличие от стандартной джавы — он поддерживает расширенный список классов без каких-либо ограничений.
JBoss Serialization исключили из участников на основании вот этого теста: eishay/jvm-serializers
Там сериализация JBoss сильно уступает Jackson Smile-у, Kryo и FST, которые попали в наше исследование.

Не понимаю, как Вы умудрились намерить для Java Standart такой "плачевный" результат.


У меня есть постоянные "измерители" полного цикла запроса и ответа на локальном и на удаленном узлах. На удаленном узле десериализация запроса, обработка запроса, сериализация ответа суммарно всегда отрабатывает менее 1 мс. На запрашиваемом узле сериализация запроса, ожидание, десериализация ответа суммарно менее 5 мс. Используется стандартная Java сериализация (из коробки). Используется ZIP для сжатия данных при передаче по сети по протоколу HTTP. По протоколу RMI результат будет еще ниже (не будет передачи надстройки HTTP протокола над передаваемыми данными по сети).


Объем переданных данных у меня не отслеживается (по косвенным признакам менее 1к в сжатом виде). Используется OpenJDK 1.8.


Чем меньше выполняется различных преобразований при сериализации — десериализации, тем лучше должен быть результат по определению. Java Standart — делает подобное, на мой взгляд, с наименьшими преобразованиями данных по сравнению со всем остальным перечисленным вами. Поэтому, думаю, что у Вас есть погрешность измерений для Java Standart.

Взял статистику по одну из запросов — минимальное время 1 мс, максимальное время — 1005 мс, среднее время — 4 мс, счетчик запросов — 71 тыс. Это время замера — отправки запроса на удаленный узел (сериализация запроса — сеть — десериализация запроса — обработка — сериализация ответа — сеть — десериализация ответа)

Во-первых, коллега, я не «умудрился намерить», а выполнил качественные измерения с использованием JMH — специального софта для измерения производительности JVM. Опубликованные результаты измерений многократно повторялись на нашем софте и железе.

Во-вторых, если вы взглянете на первые графики из раздела «Гонки», то увидите, что для Java Standard цикл сериализации/десериализации данных размером порядка 1 КБ (примерно ваш размер) у нас занял 0,007 + 0,021 = 0,028 мс. У вас же получилось 4 мс за 2 цикла сериализации/десериализации + сетевые задержки. Это, без учёта сети, в 2000/28=~71 раз медленнее нашего результата. И где здесь «плачевный» результат?..

Кстати, исходя из того, что сама фаза измерения в нашем случае длилась 5 сек (я это указывал в начале «Гонок»), то для получения значения 0,007 мс по сериализации у нас ушло 714 285 повторений с усреднением результата. Для десериализации (0,021 мс) было использовано 238 095 повторений. Эти цифры кратно больше ваших 71 000 запросов, что говорит о том, что точность опубликованных измерений выше, чем в ваших «измерителях».

Java Standart — делает подобное, на мой взгляд, с наименьшими преобразованиями данных по сравнению со всем остальным перечисленным вами.
Субъективное суждение, это лично ваше мнение.

Измерять можно по разному и ссылка на использование софта еще ни о чем не говорит. Разные люди, при использовании одного и того инструмента, могут получить разный результат. Доказано практикой.


Я Вам привел цифры ведь тоже не с потолка, а результат сбора статистики. И этот результат кардинально отличается от ваших измерений. Многократность большого значения не имеет, а лишь позволяет "подавить" различные погрешности измерений, вносимых синхронизаций часов и не равномерной загрузкой используемых внешних ресурсов (сети например).


Мои измерения строятся на фиксации временных точек непосредственно перед вызовом удаленного метода и сразу после получения результата этого вызова. Внутри вызова "спрятан" код "упаковки" объектов в поток. Какие либо другие преобразования данных отсутствуют.


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


Но мне интересно, где Вы умудрились потерять столько времени на использовании "Java Standart" в своих измерениях. Различия в JVM IBM и SUN (Oracle) я отвергаю. Я работал и с тем и другим, в них есть различия, но другого рода.


Поясните, что измерялось в вашем случае использования "Java Standart". Как реализован вызов? Сериализованы ли объекты передаваемые через сеть?

Во-вторых, если вы взглянете на первые графики из раздела «Гонки», то увидите, что для Java Standard цикл сериализации/десериализации данных размером порядка 1 КБ (примерно ваш размер) у нас занял 0,007 + 0,021 = 0,028 мс. У вас же получилось 4 мс за 2 цикла сериализации/десериализации + сетевые задержки. Это, без учёта сети, в 2000/28=~71 раз медленнее нашего результата. И где здесь «плачевный» результат?..

Вы не путаете результат своего измерения с секундами? Системные часы точнее миллисекунд измерять не позволяют!

Нет, не путаю. Речь здесь идёт именно про микросекунды (тысячные доли миллисекунды). Это результат усреднения сотен тысяч повторений сериализации/десериализации, о чём я написал выше в комментарии.
Конечно, измерять с такой точностью системные часы компьютеров не позволяют.
Сериализованы ли объекты передаваемые через сеть?
Передачи через сеть в наших измерениях нет, только сериализация/десериализация.

Рекомендую ознакомиться с Java Microbenchmark Harness (JMH).
«JMH-бенчмарк без деталей» я привёл в одном из комментариев выше. В ближайшее время добавлю этот кусок Java-кода в тело самой публикации.
Передачи через сеть в наших измерениях нет

Тогда мы говорим о совершенно разных понятиях "сериализации" и "десериализации". В моем понимании эти понятия связаны с выводом в поток и восстановлением объекта из потока.


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


И получается, что мой результат 0 мс на приемной стороне (удаленном узле) ничем не хуже вашего.

В моем понимании эти понятия связаны с выводом в поток и восстановлением объекта из потока.
У сериализации другое определение, если посмотреть даже в Wikipedia:
In computer science, in the context of data storage, serialization (or serialisation) is the process of translating data structures or object state into a format that can be stored (for example, in a file or memory buffer) or transmitted (for example, across a network connection link) and reconstructed later (possibly in a different computer environment).
Для Java, фактически, сериализация — это только преобразование Object-а в byte[]|String|..., которые можно передать по сети/сохранить в БД и т.д., но эти действия не относятся к самой сериализации.

Останемся при своих мнениях, не вижу смысла их друг другу навязывать.

Это лукавство — ваша цитата понятия сериализации. В распределенной системе (указано в вашей преамбуле) понятие сериализации одно — преобразование программного объекта в поток (массив байт).


В этом преобразовании Java Standart всегда будет работать быстрее любой другой рассмотренной вами в сравнении технологии, ввиду отсутствия других преобразований. Object -> byte[] всегда быстрее по сравнению с Object -> JSON -> byte[].

Ни одна из перечисленных библиотек не выполняет преобразований вида: Object -> JSON -> byte[].
Либо Object -> JSON, либо Object -> byte[]. В последнем случае как раз и наблюдается более высокая скорость, чем у Java Standard.

Что понимаете под Object? Java-object c полями объекта, JSON (String) или что то другое?

java.lang.Object с полями объекта

Вы понимаете, что все участвующие в сравнении библиотек предназначены для преобразования в формат отличный от byte[]? Грубо преобразует Object в строку, которая далее будет преобразована в массив байт при передаче в распределенной системе! Т.е. выполняется преобразование Object -> JSON -> byte[]. Это всегда будет работать хуже, чем прямое преобразование Object в byte[]. ВСЕГДА!


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

Вы понимаете, что все участвующие в сравнении библиотек предназначены для преобразования в формат отличный от byte[]?
Это неправда. Не путайте, пожалуйста, народ.

:-) Хорошо. У каждого свое мнение.


Но ваши выводы сомнительны.

Пробовал различные вариации JSON-сериализации и различные варианты бинарной сериализации - общая тенденция такова, что бинарные форматы быстрее за счёт того, что в них нет логически лишних данных для хранения разметки.

Конкретно, Fast JSON я нарочно не игнорировал - думаю, стоит попробовать "пропустить" через benchmark. Спасибо за наводку!

Зарегистрируйтесь на Хабре, чтобы оставить комментарий