Перегрузка нового оператора для хранения объектов в файле mmap'd - PullRequest
4 голосов
/ 13 января 2011

У меня есть программа на Linux C ++ с довольно большими требованиями к памяти. Большая часть памяти потребляется всего несколькими классами, и доступ к ней происходит достаточно редко. Я хочу переместить эти классы из основной памяти в дисковое хранилище, изменяя при этом как можно меньше существующего кода.

Идея состояла в том, чтобы переопределить оператор new для этих объектов и разместить их в области памяти mmap(). Таким образом, мои модификации кода остаются очень ограниченными, остальная часть программы может легко получить доступ к этим объектам, не зная, что что-то изменилось, и ядро ​​будет следить за тем, чтобы нужные мне объекты находились в памяти, а остальные - на диске. Я знаю, что это очень похоже на работу подкачки, но раздел подкачки обычно слишком мал для того, что нужно моей программе.

У меня есть несколько вопросов:

  • Это очень плохая идея? Знаете ли вы что-нибудь лучше, чтобы достичь того же?
  • Нужно ли мне заранее выделять максимальный размер файла и потребуется ли все это пространство на диске? Если да, поможет ли сопоставление с разреженным файлом?
  • Я не хочу писать свой собственный распределитель кучи. Могу ли я использовать существующий?
  • Когда моя программа завершит работу, файл mmap'd будет удален. Это означает, что я не хочу, чтобы какие-либо страницы записывались на диск , если только ядро ​​не удалит их из памяти. Есть ли что-то вроде lazy flag для mmap для достижения этого, или это автоматически?

Ответы [ 3 ]

2 голосов
/ 13 января 2011

Рассматривая каждый вопрос по очереди

  • Это очень плохая идея? Знаете ли вы что-нибудь лучше, чтобы достичь того же?

Не совсем понятно, чего вы надеетесь достичь этим. Linux уже поддерживает память, используемую пространством подкачки (поэтому, если ваши данные превышают физическую память, некоторые из них будут перенесены на диск). У вас проблемы с нехваткой адресного пространства или медленная работа из-за чрезмерного подкачки? Использование хранилища, поддерживаемого mmap, также не повлияет.

  • Нужно ли заранее выделять максимальный размер файла и потребуется ли все это пространство на диске? Если да, поможет ли сопоставление с разреженным файлом?

Да, файл должен быть таким же большим, как пространство, которое вы создаете. Тем не менее, вы можете начать с небольшого файла / mmap и при необходимости увеличить его (и дополнительные страницы mmap). Вы также можете использовать разреженный файл, чтобы дисковое пространство не использовалось до тех пор, пока страницы не будут записаны.

  • Я не хочу писать свой собственный распределитель кучи. Могу ли я использовать существующий?

Существуют диспетчеры кучи, которые используют хранилище с поддержкой mmap. Я видел версии malloc Doug Lea и других распределителей bibop, которые делают это.

  • Когда моя программа завершит работу, файл mmap'd будет удален. Это означает, что я не хочу, чтобы какие-либо страницы записывались на диск, если ядро ​​фактически не удалит их из памяти. Есть ли что-то вроде ленивого флага в mmap для достижения этого или это автоматически?

В этом случае вы можете просто использовать MAP_ANON и вообще не иметь файла. Тем не менее, это возвращает нас к первому вопросу, поскольку по сути дублирует то, что делает система malloc (и new). На самом деле на некоторых ОС (Solaris?) Это именно то, что делает система malloc. Основная причина, по которой я видел пользовательские mallocs на основе mmap в прошлом, заключается в постоянном хранении (поэтому файл останется после завершения процесса и будет переназначен при перезапуске).

1 голос
/ 13 января 2011

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

1 голос
/ 13 января 2011

Я могу вспомнить несколько проблем с подходом, который вы хотели бы использовать, так что это еще не ответ.

  1. Когда вы что-то «меняете», то есть проблема, с которой вы сталкиваетесь, заключается в том, что она потребляет слишком много памяти, чтобы удерживать объекты вокруг, и когда вы их удаляете (фактически не отображаете)? то есть принять то же решение, что и менеджер памяти вашей ОС?
  2. Хотя вы можете хранить двоичное представление класса в mmaped-блоке, если класс не является POD, процесс «замены» не будет выполнять то, что вы ожидаете (например, если есть члены какие кучи выделены - что с ними происходит?)
  3. память mmap'd все равно будет учитываться в вашем процессе, поэтому ваши проблемы не исчезнут ...

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

...