В настоящее время я разрабатываю приложение для трехмерной графики с использованием JOGL (привязка Java OpenGL). Короче говоря, у меня есть огромный двоичный файл ландшафта. Из-за его размера мне приходится транслировать фрагменты ландшафта во время выполнения. Таким образом, мы явно видим проблему произвольного доступа. Я уже закончил первую (и грязную :)) реализацию (возможно, многопоточную), где я использую дурацкий подход... Вот его инициализация:
dataInputStream = new DataInputStream(new BufferedInputStream(fileInputStream,4 * 1024);
dataInputStream.mark(dataInputStream.available());
И когда мне нужно прочитать (поток) специальный чанк (я уже знаю его "смещение" в файле), я делаю следующее (позор мне :)):
dataInputStream.reset();
dataInputStream.skipBytes(offset);
dataInputStream.read(whatever I need...);
Так как у меня было мало опыта, это было первое, о чем я мог подумать :) Итак, пока что я прочитал 3 полезные и довольно интересные статьи (предлагаю вам их прочитать, возможно, если вам интересна эта тема)
байтовые буферы и некучевая память – Г-н Грегори, кажется, хорошо разбирается в Java NIO.
Совет по Java: как быстро читать файлы [http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly] — интересный тест.
Статьи: Настройка производительности ввода-вывода Java [http://java.sun.com/developer/technicalArticles/Programming/PerfTuning/] — Простые рекомендации Sun, но, пожалуйста, прокрутите вниз и посмотрите " раздел «Произвольный доступ»; они показывают простую реализацию RandomAccessFile (RAF) с улучшением самобуферизации.
Г-н Грегори предоставляет несколько файлов *.java в конце своей статьи. Одним из них является бенчмаркинг между FileChannel + ByteBuffer + Mapping (FBM) и RAF. Он говорит, что заметил 4-кратное ускорение при использовании FBM по сравнению с RAF. Я запустил этот тест в следующих условиях:
- Смещение (например, место доступа) генерируется случайным образом (в области видимости файла, например, 0 - file.length());
- Размер файла 220 МБ;
- 1 000 000 обращений (75% чтения и 25% записи)
Результаты были ошеломляющими:
~ 28 сек для РАФ! ~ 0,2 сек. для FBM!
Однако его реализация RAF в этом бенчмарке не имеет самобуферизации (о ней рассказывается в 3-й статье), поэтому я предполагаю, что вызов метода "RandomAccessFile.seek" так сильно снижает производительность.
Хорошо, теперь, после всего того, что я узнал, есть 1 вопрос и 1 дилемма :)
Вопрос: когда мы сопоставляем файл с помощью «FileChannel.map», копирует ли Java все содержимое файла в MappedByteBuffer? Или просто подражает ему? Если он копирует, то использование FBM не подходит для моей ситуации, не так ли?
Дилемма: зависит от ваших ответов на вопрос...
Если сопоставление копирует файл, то, похоже, у меня есть только 2 возможных решения: RAF + самобуферизация (из 3-й статьи) или использовать позицию в FileChannel< /strong> (не с отображением)... Какой из них будет лучше?
Если сопоставление не копирует файл, то у меня есть 3 варианта: два предыдущих и сам FBM.
Изменить. Вот еще один вопрос. Некоторые из вас здесь говорят, что сопоставление не копирует файл в MappedByteBuffer. Хорошо, тогда почему я не могу сопоставить файл размером 1 ГБ, я получаю сообщение "не удалось сопоставить"...
П. С. Хотелось бы получить развернутый ответ с советами, т.к. не могу найти в инете целостной информации по этой теме.
Спасибо :)