2008-12-03 5 views
1

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

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

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

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

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

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

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

  • Джейсон

ответ

0

Просто для уточнения, mmap() в Unix-подобных систем не позволит вам получить доступ к файлам, как таковой; он просто делает содержимое файла доступным в памяти, как память. Вы не можете использовать open() для дальнейшего открытия любых содержащихся файлов. Нет такой вещи, как «mmap() способный набор файлов».

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

+0

Также узел, в котором mmap() не нажимает содержимое в памяти, он дает вам адрес виртуальной памяти, где вы можете получить контент. В первый раз файл будет извлечен с диска. (Тогда его можно оставить в памяти, если его достаточно.) – mat 2008-12-10 08:56:33

0

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

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

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

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

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

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

0

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

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

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

+0

Загрузка их в * память * не гарантирует, что операционная система не поместит их в своп. – mat 2008-12-03 13:08:02

1

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

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

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

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

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

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

+0

Во-первых, даже если имеется доступная память, некоторые страницы вашего JAR могут оказаться в свопе, потому что они не использовались в течение длительного времени. Я все еще думаю, что это плохая идея, чтобы попытаться быть более умным, чем ядро, поскольку вы не представляете, что действительно находится в ОЗУ :-) – mat 2008-12-03 23:38:28

0

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

0

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

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

0

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

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

1

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

Смежные вопросы