Как оценить размер сериализации объектов в Java, на самом деле не сериализируя их?

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

Я мог просто найти платформы об оценке объектной емкости памяти на основе инструментария Java. Я протестировал classmexer, который не близко подошел к размеру сериализации и sourceforge SizeOf.

В небольшом тестовом сценарии SizeOf составлял приблизительно 10% неправильно и 10x быстрее, чем сериализация. (Все еще переходные повреждения оценка полностью и с тех пор например, ArrayList является переходной, но сериализируется как Массив, не легко исправить SizeOf. Но я мог жить с этим),

С другой стороны, 10x быстрее с 10%-й ошибкой не кажется очень хорошим. Какие-либо идеи, как я мог добиться большего успеха?

Обновление: Я также протестировал ObjectSize (http://sourceforge.net/projects/objectsize-java). Результаты кажутся просто хорошими для объектов non-inheritating :(

15
задан Ciro Santilli 新疆改造中心法轮功六四事件 2 May 2015 в 20:15
поделиться

4 ответа

Размер, занимаемый классом во время выполнения, не обязательно влияет на его размер в памяти. Пример, который вы упомянули, - это временные поля. Другие примеры включают, когда объекты реализуют Externalizable и сами обрабатывают сериализацию.

Если объект реализует Externalizable или предоставляет readObject () / writeObject () , то лучше всего сериализовать объект в буфер памяти, чтобы узнать размер. Это будет не быстро, но точно.

Если объект использует сериализацию по умолчанию, вы можете изменить SizeOf, чтобы учесть временные поля.

После сериализации многих из тех же типов объектов вы можете создать «профиль сериализации» для этого типа, который коррелирует сериализованный размер с размером времени выполнения из SizeOf. Это позволит вам быстро оценить сериализованный размер (с помощью SizeOf), а затем сопоставить его с размером времени выполнения, чтобы получить более точный результат, чем тот, который предоставляется SizeOf.

5
ответ дан 1 December 2019 в 04:27
поделиться

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

Например, вы сериализуете серию объектов A, B и C одного и того же класса, которые содержат по два объекта o1 и o2 в каждом объекте. Предположим, что накладные расходы объекта составляют 100 байт, и предположим, что объекты выглядят следующим образом:

Object shared = new Object();
Object shread2 = new Object();

A.o1 = new Object()
A.o2 = shared


B.o1 = shared2
B.o2 = shared


C.o1 = shared2
C.o2 = shared

Для простоты мы можем сказать, что общие объекты занимают 50 байтов для сериализации, а размер сериализации A равен 100 (накладные расходы) + 50 (o1 ) + 50 (o2) = 200 байт. Можно было бы сделать аналогичную наивную оценку и для B и C. Однако, если все три сериализованы одним и тем же потоком вывода объекта перед вызовом сброса, вы увидите в потоке сериализацию A и o1 и o2, затем сериализацию B и o1 для b, НО ссылка на o2, поскольку это был тот же объект, который уже был сериализован .Допустим, ссылка на объект занимает 16 байтов, размер B теперь равен 100 (накладные расходы) + 50 (o1) + 16 (ссылка для o2) = 166. Итак, размер, который требуется для сериализации, теперь изменился! Мы могли бы сделать аналогичный расчет для C и получить 132 байта с двумя кэшированными объектами, поэтому размер сериализации для всех трех объектов отличается с разницей в ~ 33% между самым большим и самым маленьким.

Таким образом, если вы не сериализуете весь объект без кеша каждый раз, трудно точно оценить размер, необходимый для сериализации объекта.

5
ответ дан 1 December 2019 в 04:27
поделиться

Не может быть способа оценить сериализованный размер объекта с хорошей точностью и скоростью. Например, некоторым объектом может быть кэш цифр числа Пи, который конструируется во время выполнения, задавая только нужную вам длину. Таким образом, он сериализует только 4 байта атрибута 'length', в то время как объект может использовать сотни мегабайт памяти для хранения этого числа Пи.

Единственное решение, которое я могу придумать, это добавить свой собственный интерфейс с методом int estimateSerializeSize(). Для каждого объекта, реализующего этот интерфейс, вам нужно будет вызывать этот метод, чтобы получить нужный размер. Если какой-то объект не реализует его - вам придется использовать SizeOf.

2
ответ дан 1 December 2019 в 04:27
поделиться

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

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

3
ответ дан 1 December 2019 в 04:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: