Ehcache - почему записи такие большие? - PullRequest
1 голос
/ 27 июля 2011

У меня довольно простая модель данных, например:

class MyParent {
     // 7 fields here, some numeric, some String, not longer than 50 chars total
     Set<MyChild> children;
}

class MyChild {
    int ownerId;
    // 3 more fields, numeric or dates
}

MyParent, MyChild и MyParent.children все кэшируются с read-only.

У меня 40 000 экземпляров MyParent и 100 000 экземпляров MyChild. Это дает 180 000 записей в кэше (если добавить 40 000 MyParent.children).

Я хочу кэшировать все, сгруппированные по ownerId. Не желая изобретать велосипед, я хотел использовать кеш запросов, например:

Query query = session
                .createQuery(
                        "select distinct p from MyParent p join fetch p.children c where c.ownerId = :ownerId");
query.setParameter("ownerId", ownerId);
query.setCacheable(true);
query.setCacheRegion("MyRegion");
query.list();

Для всех 1500 значений ownerId.

Кэш работает, но я заметил, что он огромен! Измеряется с Ehcache.calculateInMemorySize(), в среднем каждая запись превышает один килобайт. Для кеширования ~ 180 000 записей мне понадобится более 200 МБ. Это возмутительно, учитывая, что сами записи намного меньше.

Откуда появляются накладные расходы и как их уменьшить?

1 Ответ

2 голосов
/ 28 июля 2011

Я не уверен из вопроса, какой кеш вы использовали для математики, но позвольте мне использовать класс MyParent в качестве примера.Учитывая то, что вы объяснили о классе, на 64-битной виртуальной машине с включенным сжатым доступом экземпляр MyParent будет иметь размер чуть меньше 500 байт в куче.И это без Set, я объясню почему позже (иначе было бы еще 128 байтов).Кэш также должен содержать ключ для этой записи, который добавляется в расчет ...

Hibernate напрямую не использует первичный ключ, ключ для чего-то, что он хранит в кэше, а запись CacheKey.,Этот экземпляр содержит pk объекта, который представляет значение, а также четыре других поля: тип, отображение типа Hibernate;entityOrRoleName, имя объекта или роли роли коллекции;tenantId, идентификатор арендатора, связанный с этими данными;и, наконец, hashCode для pk (см. org.hibernate.type.Type.getHashCode).

Теперь, к сожалению, на этом все не заканчивается, значение для этой записи не экземпляр MyParent, ноэкземпляр CacheEntry.На этот раз, помимо дополнительных метаданных (подкласс, имя сущности, по умолчанию FQCN; lazyPropertiesAreUnfetched, логическое значение и значение блокировки optimisitc вне сущности), этот экземпляр по-прежнему не содержит экземпляр MyParent, но представляет собой разобранное представлениеЭто.Это представление является массивом состояния (всех свойств) сущности.

Полагаю, что с этой информацией "оценочные" размеры ваших спящих кэшей будут иметь больше смысла.Я хотел бы подчеркнуть, что это только оценки, и если я правильно помню, как они рассчитываются, это, вероятно, немного выше реальности.Действительно, некоторая информация, например, в CacheKey, вероятно, должна учитываться иначе.Начиная с Ehcache 2.5, вы сможете включить настройку памяти на кешах (и даже на уровне CacheManager).Когда это будет сделано, записи в кэш будут точно измерены, а calcInMemorySize () даст вам реальный измеренный размер кеша.

Вы можете скачать бета-версию для 2.5 прямо сейчас с ehcache.org.Также обратите внимание, что при использовании байтовых размеров в ваших кэшах механизм определения размеров будет учитывать эти общие экземпляры для всех кэшированных записей в типах кэша Hibernate.Вы можете прочитать больше о том, как все это работает здесь: http://ehcache.org/documentation/configuration.html#Memory_Based_Cache_Sizing_Ehcache_2.5_and_higher

Надеюсь, что это поможет вам разобраться во всем этом ... Алекс

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