Дисковый кэш в одном файле - зачем?
От: avpavlov  
Дата: 08.07.10 15:47
Оценка:
Стокнулся с неприятной проблемой при использовании Ява библиотеки ehcache.

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

При размере объекта, скажем 300мб, сериализованный размер доходит до 450мб, а в процессе сериализации из-за перевыделения буфера, может получиться, что потребуется ещё один доп. буфер размером вплоть до 450Мб-1 байт.

Итого, чтобы сериализовать 300мб объект на диск, требуется дополнительно вплоть до 900мб памяти!!!! 900мб для операции которая требует несколько килобайт, если тупо сразу сбросить на диск!!!!

Собственно вопрос к знатокам — а какие вообще могут быть причины, чтобы хранить дисковый кэш в одном файле, вместо подхода 1 объект = 1 файл?

— Дефрагментация диска? Для одного большого файла эта проблема более насущная. Да и вообще это не должно быть заботой библиотеки кэша на Яве, это забота файловой системы.
— Скорость? А чего может быть быстрее подхода 1 файл=1 объект?
— Много файлов замедляют доступ к папке? — ну значит надо не хранить файлы в одной папке, а структурировать. Допустим, если хранить 2 уровня папок (по 1000 на каждом) и по 1000 файлов в папке — то это уже 1 млрд объектов, причём нам достаточно хранить счётчик файлов для миллиона папок ~ 2Мб.
— Потеря места на диске за счёт неиспользуемого места после конца файла в последнем кластере? Допустим, средняя потеря 4КБ (для размера кластера 8Кб). Для того, чтобы потерять хотя бы гигабайт, нужно 250 000 объектов, что довольно-таки немало. Про ehcache тут вообще нет смысла говорить — у них при удалении элементов кэша, никакой дефрагментации, слияния блоков или уменьшения размера файла, так что если я в цикле буду добавлять объект в кэш, потом удалять, потом увеличивать на 1 байт, и повторять, то суммарный размер файла будет равен сумме всех элементов, просто потому, что каждый следующий блок требует больше места, и он будет выделяться заново в конце файла. Пусть есть библитека, которая умеет дефрагментировать — а оно того стоит?

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

Что думаете, не упустил ли я ещё каких то аргументов? Потому что в библиотеке Apache JCS используется тот же подход. И я начинаю сомневаться
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.