Это выглядит длинным вопросом из-за всего контекста. В романе есть два вопроса. Спасибо, что нашли время, чтобы прочитать это и оказать помощь.
Ситуация
Я работаю над масштабируемой реализацией хранилища данных, которая может поддерживать работу с файлами данных с нескольких КБ до ТБ или больше по размеру в 32-разрядной или 64-разрядной системе.
В хранилище данных используется проект "Копировать-на-запись"; всегда добавляя новые или измененные данные в конец файла данных и никогда не делая на месте редактирования существующих данных.
Система может содержать 1 или более баз данных; каждый из которых представлен файлом на диске.
Детали реализации не важны; единственной важной деталью является то, что мне нужно постоянно добавлять файл и расширять его с КБ, до МБ, до ГБ до ТБ и в то же время случайным образом пропускать файл для операций чтения для ответа на запросы клиентов.
Первоклассники Мысли
На первый взгляд я знал, что хочу использовать файлы с отображением памяти, чтобы я мог подталкивать бремя эффективного управления состоянием данных в памяти на хост-систему и из моего кода.
Тогда весь мой код, о котором нужно беспокоиться, - это сериализовать операции добавления к файлу on-write и позволять любому числу одновременных читателей искать в файле ответы на запросы.
Дизайн
Поскольку отдельные файлы данных могут вырасти за пределы 2 Гбайт MappedByteBuffer, я ожидаю, что мой проект должен будет включать слой абстракции, который принимает смещение записи и преобразует его в смещение внутри определенного сегмента 2 ГБ.
До сих пор так хорошо...
Проблемы
Здесь я начал зависеть и подумал, что лучший способ сделать это может пойти другим дизайном (предлагаемым ниже).
Отчитывая здесь примерно 20 "связанных с памятью" вопросов, связанных с SO, кажется, что вызовы mmap чувствительны к желанию непрерывных прогонов памяти при распределении. Так, например, на 32-битной ОС хоста, если я попытался создать файл размером 2 ГБ, из-за фрагментации памяти, мои шансы тонкие, что сопоставление будет успешным, и вместо этого я должен использовать что-то вроде серии из 128 МБ-сопоставлений, чтобы вытащить целую файл.
Когда я думаю об этом дизайне, даже скажу, используя размеры 1024 мегабайта mmap, для СУБД, размещающей несколько огромных баз данных, все из которых представлены, например, 1TB файлами, теперь у меня есть тысячи областей памяти с памятью и в моем собственном тестировании Windows 7, пытаясь создать несколько сотен mmaps в файле с несколькими GB, я не просто столкнулся с исключениями, я фактически получил JVM для segfault каждый раз, когда я пытался выделить слишком много, и в одном случае получил видео в моей Windows 7 для вырезания и повторной инициализации с помощью всплывающего окна OS-error, которое я никогда раньше не видел.
Независимо от аргумента "вы никогда не будете обрабатывать файлы, которые являются большими" или "это надуманный пример", тот факт, что я мог бы что-то кодировать с таким типом побочных эффектов, поставил мою внутреннюю тревогу на высокий уровень -alert и рассмотрел альтернативный имп (ниже).
BESIDES, которые выдают, мое понимание файлов с отображением памяти заключается в том, что я должен повторно создавать сопоставление каждый раз, когда файл растет, поэтому в случае этого файла, который добавляется только в дизайне, он буквально постоянно растет.
Я могу в какой-то мере бороться с этим расширением файла в кусках (скажем, 8 Мбайт за раз) и только заново создавать сопоставление каждые 8 МБ, но необходимость постоянно воссоздавать эти сопоставления вызывает у меня нервную реакцию, особенно без явно функция unmap, поддерживаемая в Java.
Вопрос № 1 из 2
Учитывая все мои выводы до этого момента, я бы убрал файлы с отображением памяти в качестве хорошего решения для решений с высокой степенью защиты или для решения только для чтения, но не для письменных решений, учитывая необходимость воссоздания отображение постоянно.
Но затем я оглядываюсь вокруг ландшафта вокруг меня с такими решениями, как MongoDB, охватывающий все файлы, помеченные памятью, и мне кажется, что здесь отсутствует какой-то основной компонент (я знаю, что он выделяет что-то вроде 2 ГБ экстентов на время, так что я думаю, что они работают над стоимостью повторной карты с этой логикой и помогают поддерживать последовательные прогоны на диске).
В этот момент я не знаю, является ли проблема Java отсутствием операции unmap, которая делает это намного более опасным и непригодным для моего использования, или если мое понимание неверно, и кто-то может указать мне на север.
Альтернативный дизайн
Альтернативный дизайн для карты памяти, предложенной выше, которую я буду использовать, если мое понимание mmap правильное:
Определите прямой ByteBuffer разумного настраиваемого размера (примерно 2, 4, 8, 16, 32, 64, 128 КБ), что делает его легко совместимы с любой платформой хоста (не нужно беспокоиться о том, что сама СУБД вызывает сценарии переполнения) и используя исходный FileChannel, выполните чтение с определенным смещением файла объемом 1 бит-емкость, одновременно полностью переносящим файлы с отображением памяти.
Недостатком является то, что теперь мой код должен беспокоиться о таких вещах, как "Я достаточно читал из файла, чтобы загрузить полную запись?"
Другая сторона заключается в том, что я не могу использовать логику виртуальной памяти ОС, позволяя ей автоматически сохранять "горячие" данные в памяти; вместо этого мне просто нужно надеяться, что логика кэша файлов, используемая ОС, достаточно велика, чтобы сделать что-то полезное для меня здесь.
Вопрос № 2 из 2
Я надеялся получить подтверждение моего понимания всего этого.
Например, возможно, кеш файл является фантастическим, что в обоих случаях (отображение в памяти или прямое чтение) операционная система будет поддерживать как можно больше моих горячих данных, а разница в производительности для больших файлов незначительна.
Или, может быть, мое понимание чувствительных требований к файлам с отображением памяти (непрерывная память) неверно, и я могу игнорировать все это.