2008-10-10 2 views
69

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

В частности, я обеспокоен ниже, в порядке важности:

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

ответ

44

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

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

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

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


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

1

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

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

18

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

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

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

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

В сопоставленном мире, напротив, представьте себе два процесса, которые «пишут». Они делают это, делая «хранилища памяти», что приводит к тому, что 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().

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

43

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

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

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

Не будет ли бинарный поиск медленным, поскольку страницы будут прочитаны для каждой попытки? Или операционная система достаточно умна, чтобы эффективно справляться с этим? – jjxtra 2013-11-02 04:12:36

+1

Я полагаю, что использование ввода-вывода с отображением памяти является бесполезным для двоичного поиска, так как поиск будет иметь доступ только к нескольким отдельным клавишам в относительно отдаленных местах памяти, но ОС будет загружать на 4 тыс. Страниц для каждого такого запроса. Но опять же, файл с частями не сильно меняется, поэтому кеш помогает покрыть это. Но, строго говоря, я считаю, что традиционный поиск/чтение будет лучше здесь. Наконец, 1 мил в наши дни не так много. Почему бы просто не хранить все это в ОЗУ? – 2013-11-11 14:50:47

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