Как оценить размер сериализации объектов в Java без фактической их сериализации? - PullRequest
15 голосов
/ 18 июня 2010

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

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

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

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

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

Ответы [ 4 ]

5 голосов
/ 18 июня 2010

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

Например, вы сериализуете серию объектов 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. Так что размер, необходимый для сериализации, теперь изменился! Мы могли бы выполнить вычисление simialr для C и получить 132 байта с кэшированием двух объектов, поэтому размер сериализации для всех трех объектов будет разным с разницей в ~ 33% между самым большим и самым маленьким.

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

5 голосов
/ 18 июня 2010

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

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

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

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

3 голосов
/ 18 июня 2010

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

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

2 голосов
/ 18 июня 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...