Каковы преимущества файлов, сопоставленных с памятью?


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

в частности, меня беспокоит следующее, в порядке важности:

  • параллелизм
  • произвольный доступ
  • производительность
  • простота использования
  • мобильность
4 74

4 ответа:

Я думаю, что преимущество действительно в том, что вы уменьшаете количество копирования данных, необходимых по сравнению с традиционными методами чтения файла.

Если ваше приложение может использовать данные "на месте" в файле с отображением памяти, он может войти без копирования; если вы используете системный вызов (например, Linux pread ()), то это обычно включает в себя ядро, копирующее данные из своих собственных буферов в пользовательское пространство. Это дополнительное копирование не только занимает много времени, но и снижает эффективность процессора кэширование путем доступа к этой дополнительной копии данных.

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

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


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

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

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

  • параллелизм-у меня была проблема реализации, когда он иногда сопоставлял файл несколько раз в одном и том же пространстве процесса. Насколько я помню, это была проблема, потому что иногда система не могла найти достаточно большой свободный блок виртуальной памяти для сопоставления файла. Решение состояло в том, чтобы только сопоставить файл один раз и thunk все вызовы к нему. В ретроспектива с использованием полномасштабной службы Windows была бы классной.
  • произвольный доступ-двоичный поиск, безусловно, произвольный доступ и молниеносно
  • производительность-поиск очень быстро. По мере ввода пользователем всплывающего окна отображается список соответствующих номеров деталей продукта, список сжимается по мере продолжения ввода. Нет заметного отставания при наборе текста.

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

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

Это может быть очень удобно, и в зависимости от интерфейса виртуальной памяти может повысить производительность. Повышение производительности может произойти, потому что операционная система теперь получает возможность управлять этим бывшим "файловым вводом-выводом" вместе со всем вашим другим программным доступом к памяти и может (теоретически) использовать алгоритмы подкачки и т. д., которые она уже использует для поддержки виртуальной памяти для остальное программы. Однако это зависит от качества вашей базовой системы виртуальной памяти. Анекдоты, которые я слышал, говорят, что системы виртуальной памяти Solaris и *BSD могут показывать лучшие улучшения производительности, чем система VM но у меня нет эмпирических данных, чтобы подтвердить это. МММ.

параллелизм приходит в картину, когда вы рассматриваете возможность нескольких процессов, использующих один и тот же "файл" через сопоставленную память. В модели чтения / записи, если два процесса записаны в одну и ту же область файла, вы можете быть почти уверены, что один из данных процесса поступит в файл, перезаписывая данные другого процесса. Вы получите одно или другое, но не какое-то странное смешение. Мне пришлось признаюсь, я не уверен, что это поведение предписано каким-либо стандартом, но это то, на что вы можете в значительной степени положиться. (Это на самом деле agood следующий вопрос!)

в отображенном мире, напротив, представьте себе два процесса, оба "пишущих". Они делают это, делая "хранилища памяти", которые приводят к тому, что O/s подкачивает данные на диск-в конечном итоге. Но в то же время можно ожидать, что перекрывающиеся записи произойдут.

вот пример. Скажем, у меня есть два процесса, оба пишущих 8 байт при смещении 1024. Процесс 1 пишет '11111111', а процесс 2 пишет'22222222'. Если они используют файловый ввод-вывод, то вы можете себе представить, что в глубине O/S есть буфер, полный 1s, и буфер, полный 2s, оба направляются в одно и то же место на диске. Один из них доберется туда первым, а другой-вторым. В этом случае побеждает второй. , если я использую сопоставленный с памятью подход к файлам, процесс 1 собирается перейти в хранилище памяти размером 4 байта, а затем другое хранилище памяти размером 4 байта (предположим, что это не максимальный размер хранилища памяти). Процесс 2 будет делать то же самое. В зависимости от того, когда запущены процессы, вы можете ожидать увидеть любое из следующих:

11111111
22222222
11112222
22221111

решение этой проблемы заключается в использовании явного взаимного исключения-что, вероятно, является хорошей идеей в любом случае. Во всяком случае, вы полагались на O/S, Чтобы сделать "правильную вещь" в случае ввода-вывода файла чтения/записи.

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

Edit with one gotcha: когда вы используете сопоставленные файлы, есть соблазн встроить указатели на данные в файл, в сам файл (подумайте, связанный список, хранящийся в сопоставленном файле). Вы не хотите этого делать, так как файл может быть отображен в разные абсолютные адреса в разное время или в разных процессах. Вместо этого используйте смещения в пределах сопоставленный файл.

параллелизм будет проблемой. Произвольный доступ проще Производительность хороша до большой. Простота использования. Не так хорошо. Переносимость - не такая уж и горячая.

Я использовал их на Солнечной системе давным-давно, и это мои мысли.