Каковы преимущества отображаемых в память файлов? - PullRequest
76 голосов
/ 10 октября 2008

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

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

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

Ответы [ 4 ]

50 голосов
/ 11 октября 2008

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

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

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

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


Очевидный недостаток файлов, отображаемых в память, в 32-битной ОС - вы легко можете исчерпать адресное пространство.

45 голосов
/ 10 октября 2008

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

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

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

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

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

Это может быть очень удобно, и в зависимости от интерфейса виртуальной памяти может повысить производительность. Повышение производительности может произойти, потому что операционная система теперь может управлять этим прежним «файловым вводом-выводом» вместе со всем другим программным доступом к памяти и может (теоретически) использовать алгоритмы подкачки и т. Д., Которые она уже использует для поддержки виртуальная память для отдыха вашей программы. Однако это зависит от качества вашей системы виртуальной памяти. Анекдоты, которые я слышал, говорят, что системы виртуальной памяти Solaris и * BSD могут показывать лучшие улучшения производительности, чем системы виртуальных машин Linux - но у меня нет эмпирических данных, подтверждающих это. YMMV.

Параллельность входит в картину, когда вы рассматриваете возможность использования несколькими процессами одного и того же «файла» в отображенной памяти. В модели чтения / записи, если два процесса записывают в одну и ту же область файла, вы можете быть в значительной степени уверены, что одна из данных процесса будет поступать в файл, перезаписывая данные другого процесса. Вы получите одно или другое - но не какое-то странное смешение. Я должен признать, что я не уверен, является ли это поведением, предписанным каким-либо стандартом, но это то, на что вы в значительной степени можете положиться. (На самом деле это хороший вопрос для продолжения!)

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

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

11111111
22222222
11112222
22221111

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

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

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

1 голос
/ 10 октября 2008

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

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

...