кэширование tar внутри jvm для более быстрого ввода / вывода файлов? - PullRequest
1 голос
/ 03 декабря 2008

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

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

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

Я нашел проект apache VFS, который может читать информацию из файла tar, но я не уверен из их документации, если вы можете указать что-то типа "также, прочитать весь файл tar в память и удерживать его там .." ».

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

Кроме того, мы используем 64-битную ОС с 32 гигабайтами оперативной памяти, наши 300 000 файлов занимают от 1,5 до 2,5 гигабайт пространства. Конечно, мы можем прочитать файл объемом 2,5 гигабайта в память гораздо быстрее, чем небольшие файлы размером несколько килобайт размером 300 КБ.

Спасибо за ввод!

  • Jason

Ответы [ 8 ]

1 голос
/ 18 января 2009

Если у вас есть 300 000 файлов, к которым вам нужен быстрый доступ, вы можете использовать базу данных, не реляционную, а простую с ключом-значением, например http://www.space4j.org/.. возможно, довольно быстрое увеличение во время выполнения.

1 голос
/ 03 декабря 2008

Вы можете попробовать поместить все файлы в JAR-файл и поместить его в путь к классам. Java использует некоторые встроенные приемы, чтобы сделать чтение из файла JAR очень быстрым. Это также сохранит каталог всех файлов в ОЗУ, поэтому вам не нужно будет обращаться к диску, чтобы найти файл (это происходит до того, как вы сможете начать его загрузку).

JVM не будет загружать весь JAR-файл в оперативную память одновременно, и вы, вероятно, в любом случае не захотите этого, потому что ваша машина начнет подкачку. Но он сможет находить фрагменты очень быстро, потому что он будет держать файл открытым все время, и, следовательно, вы не потеряете время открытия / закрытия файлового ресурса.

Кроме того, поскольку вы постоянно используете этот единственный файл, есть вероятность, что ОС будет дольше хранить его в файловых кешах.

Наконец, вы можете попробовать сжать JAR. Хотя это может звучать как плохая идея, вы должны попробовать. Если небольшие файлы сжимаются очень хорошо, время распаковки с текущими процессорами намного меньше, чем время чтения данных с диска. Если вам не нужно хранить промежуточные данные где-либо, вы можете передавать несжатые данные клиенту без необходимости записи в файл (что разрушит всю идею). Недостатком этого является то, что он потребляет циклы процессора, и если ваш процессор занят (просто проверьте с помощью какого-либо инструмента загрузки; если он выше 20%, то вы проиграете), то вы замедлите весь процесс.

Тем не менее, когда вы используете протокол HTTP, вы можете сказать клиенту, что отправляете сжатые данные! Таким образом, вам не нужно распаковывать данные и , вы можете загружать очень маленькие файлы.

Основной недостаток решения JAR: вы не можете заменить JAR, пока работает сервер. Таким образом, замена файла означает, что вам придется перезапустить сервер.

0 голосов
/ 03 декабря 2008

Вам нужно загрузить всю информацию в HashTable .

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

0 голосов
/ 03 декабря 2008

Если вы используете Linux, я бы попробовал старый добрый RAM диск . Вы можете придерживаться текущего способа ведения дел и просто радикально снизить затраты на ввод-вывод. Вы не связаны с памятью JVM и все еще можете легко заменить содержимое.

Как вы говорили о VFS: у него также есть провайдер RAM-диска , но я все равно сначала попробую подход с собственным RAM-диском.

0 голосов
/ 03 декабря 2008

Разместите файлы на 10 разных серверах и вместо прямой отправки запросов отправьте клиенту HTTP-перенаправления (или эквивалентные) с URL-адресом, по которому они могут найти нужный файл. Это позволяет распределить нагрузку. Сервер просто отвечает на быстрые запросы, и (большие) загрузки распределяются по нескольким машинам.

0 голосов
/ 03 декабря 2008

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

Что бы я сделал, это создал сервис, который возвращал бы файл как структуру объекта из любого параметра, который вы используете. Затем внедрите некоторый механизм кэширования вокруг этого сервиса. Тогда все дело в настройке кеша. Если вам действительно нужно загрузить все в память, настройте кэш на использование большего объема памяти. Если некоторые файлы используются гораздо чаще, чем другие, может быть достаточно кэшировать только эти ...

Мы могли бы дать вам лучший ответ, если бы знали больше о том, чего вы пытаетесь достичь.

0 голосов
/ 03 декабря 2008

Я думаю, что вы все еще думаете о старом режиме памяти / диска.

mmap здесь не поможет, потому что эта старая память / диск давно исчезла. Если вы отобразите файл, ядро ​​вернет вам указатель на некоторую виртуальную память , которую вы сможете использовать по своему усмотрению, не загрузит файл в real Память сразу, он сделает это, когда вы запросите часть файла, и загрузит только те страницы, которые вы запрашиваете. (То есть страница памяти, обычно размером около 4 КБ.)

Вы говорите, что эти файлы размером 300 КБ занимают от 1,5 до 2,5 ГБ дискового пространства. Если есть вероятность, что вы можете добавить на сервер 2 (или лучше, 4) гигабайта ОЗУ, вы бы очень лучше оставили бы эту функцию чтения с диска ОС, если у нее достаточно ОЗУ для загрузки файлы в некотором дисковом кеше, он будет, и из них любой read () на них даже не попадет на диск. (Будет сохранено время в inode, если вы не смонтировали том с noatime.)

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

Если у вас достаточно ОЗУ, чтобы ОС могла выполнять кэширование на диске, и вы действительно хотите, чтобы файлы загружались, вы всегда можете выполнить небольшой скрипт / программу, которая пройдет через вашу иерархию и прочитает все файлы. (Ничего не делая.) Операционная система загрузит их с диска в кэш-память, но вы не сможете узнать, останутся ли они там, если ОС потребуется память. Поэтому, как я уже говорил, вы должны позволить ОС справиться с этим и выделить для этого достаточно оперативной памяти.

Вы должны прочитать Лак Заметки архитектора , где phk говорит вам своими словами, почему то, чего вы пытаетесь достичь, намного лучше осталось от ОС, которая всегда будет лучше знать JVM, что находится в оперативной памяти, а что нет.

0 голосов
/ 03 декабря 2008

Просто чтобы уточнить, <a href="http://linux.die.net/man/2/mmap" rel="nofollow noreferrer">mmap()</a> в Unix-подобных системах не позволит вам получить доступ к файлам как таковым; он просто делает содержимое файла доступным в памяти, как память. Вы не можете использовать open() для дальнейшего открытия любых содержащихся файлов. Не существует такого понятия, как «mmap() набор файлов».

Разве вы не можете просто добавить проход, который первоначально загружает все ваши "шаблоны", а затем быстро находит их, основываясь на чем-то простом, например, на хэше имени каждого? Это должно позволить вам использовать вашу память и получить доступ к O (1) для любого шаблона.

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