Які переваги картографічних файлів?


89

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

Мене, зокрема, турбує наступне в порядку важливості:

  • паралельність
  • довільний доступ
  • продуктивність
  • простота використання
  • портативність

Відповіді:


56

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

Якщо ваша програма може використовувати дані "на місці" у файлі, що відображається у пам'яті, вона може надійти без копіювання; якщо ви використовуєте системний виклик (наприклад, Linux pread ()), то це, як правило, передбачає копіювання ядра даних із власних буферів у користувацький простір. Це додаткове копіювання не тільки вимагає часу, але зменшує ефективність кеш-пам'яті процесора, отримуючи доступ до цієї додаткової копії даних.

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

Недоліком є ​​відсутність асинхронного інтерфейсу для відображених у пам’яті файлів - якщо ви намагаєтеся отримати доступ до сторінки, яка не зіставлена, це генерує помилку сторінки, після чого потік чекає введення / виводу.


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


4
Принаймні в Windows ви можете зіставити кілька 32-бітних видів великого файлу mmap - що може бути більш ефективним, ніж спроби мати справу з дуже великими файлами за допомогою звичайної функції ЕПТ
Мартін Бекетт

@MarkR Ви писали, що "його додаткове копіювання не тільки вимагає часу, але зменшує ефективність кеш-пам'яті процесора, отримуючи доступ до цієї додаткової копії даних ". ( наголос мій). Чи можете ви пояснити, як додаткова буферна копія в ядрі перешкоджає ефективності кеш-пам'яті процесора?
Geek

4
@Geek отримує вдвічі більше пам'яті = вдвічі більше витраченого кешу (дуже приблизно).
user253751

49

Я використав файл, зіставлений із пам'яттю, для реалізації функції "автозавершення" під час введення користувачем тексту. У мене є понад 1 мільйон номерів деталей товару, що зберігаються в одному файлі індексу. У файлі є типова інформація про заголовки, але основна частина файлу - це гігантський масив записів фіксованого розміру, відсортованих за ключовим полем.

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

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

1
Чи не буде двійковий пошук повільним, оскільки сторінки читаються при кожній спробі? Або операційна система досить розумна, щоб ефективно з цим боротися?
jjxtra

1
Я вважаю, що використання вкладеного / виведеного пам’яті досить марно для двійкового пошуку, оскільки пошук матиме доступ лише до кількох одиничних клавіш у відносно віддалених місцях пам’яті, але ОС завантажуватиметься на 4 тис. Сторінок для кожного такого запиту. Але знову ж таки, файл із частинами сильно не змінюється, тому кеш допомагає це приховати. Але, строго кажучи, я вважаю, що традиційні пошуки / читання тут були б кращими. Нарешті, 1 мільйон - це не багато в наші дні. Чому б просто не зберегти все це в оперативній пам’яті?
свині

5
@ the swine і PsychoDad, моя оригінальна відповідь була з 2008 року, а фактична реалізація цієї функції автоматичного заповнення на карту пам'яті була приблизно в 2004-2005 або близько того. Споживання 800-1000 МБ фізичної пам’яті для завантаження всього файлу не було хорошим рішенням для нашої бази користувачів. Розраховане на карту пам'яті рішення було дуже швидким та ефективним. Це пішло на ноги, і я пам’ятаю це з любов’ю ще з часів мого раннього розвитку. :)
Брайан Енсінк

@BrianEnsink: добре, це має сенс. я не очікував, що кожен запис буде дорівнює 1 кБ. тоді, звичайно, підкачковий підхід стає більш ефективним. приємно :)
свині

22

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

Замість того, щоб шукати, писати та читати у файлі, ви відображаєте його у пам’яті та просто отримуєте доступ до бітів там, де ви їх очікуєте.

Це може бути дуже зручно, і в залежності від інтерфейсу віртуальної пам'яті може підвищити продуктивність. Покращення продуктивності може відбутися, оскільки операційна система тепер може керувати цим колишнім "файловим введенням-виведенням" разом із усіма іншими програмами, що мають доступ до пам'яті, і може (теоретично) використовувати алгоритми підкачки та ін., Що вона вже використовує для підтримки віртуальна пам’ять для решти вашої програми. Однак це залежить від якості вашої основної системи віртуальної пам'яті. Анекдоти, про які я чув, говорять, що системи віртуальної пам'яті Solaris та * BSD можуть покращити продуктивність, ніж система віртуальних машин Linux, але я не маю емпіричних даних, щоб підтвердити це. YMMV.

Паралельність з’являється в картині, коли ви розглядаєте можливість декількох процесів із використанням одного і того ж «файлу» через зіставлену пам’ять. У моделі читання / запису, якщо два процеси писали в одну і ту ж область файлу, ви могли б бути майже впевнені, що одна з даних процесу надійде у файл, замінивши дані іншого процесу. Ви отримаєте то одне, чи інше - але не якесь дивне змішування. Я повинен визнати, що я не впевнений, чи це поведінка, передбачена будь-яким стандартом, але це те, на що ви могли б покластися. (Це насправді 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 ().

Редагувати за допомогою однієї затримки: Коли ви використовуєте зіставлені файли, виникає спокуса вбудувати покажчики до даних у файлі, у самому файлі (подумайте, пов’язаний список зберігається у зіставленому файлі). Ви не хочете цього робити, оскільки файл може бути зіставлений з різними абсолютними адресами в різний час або в різних процесах. Замість цього використовуйте зсуви в межах зіставленого файлу.


1

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

Я давно використовував їх на системі Sun, і це мої думки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.