В системе виртуальной памяти виртуальное адресное пространство означает, что виртуальные страницы могут отображаться где угодно. Вам не нужны большие непрерывные блоки физической памяти. Если у вас возникают проблемы с фрагментацией виртуального адресного пространства, вам может потребоваться другая стратегия управления памятью.
Однако для большинства опций код вашего приложения должен быть осведомлен о стратегии управления памятью на каком-то уровне. Я не верю, что есть быстрое решение этой проблемы - вы, вероятно, готовы к достаточно серьезной операции, чтобы ее решить. Ни один из этих вариантов не прост в реализации, вам придется найти тот, который с наибольшей вероятностью сработает в вашем конкретном случае.
Основные параметры, которые я вижу, это: пользовательские распределители памяти, что-то, связанное с AWE (см. Ниже) или перестройка стратегии выделения памяти в приложении.
Вариант 1: Пользовательские распределители памяти
Пользовательские распределители памяти нередки в кругах C и C ++. Возможно, вы сможете реализовать нечто подобное. Вам доступны две возможности:
Создайте распределитель памяти с механизмом, который пытается объединить смежные свободные блоки в один больший блок (вы можете выполнить это как часть попытки восстановления после неудачного выделения памяти). Это может позволить вам прозрачно управлять памятью без ведома приложения. Реализация этого была бы сложной и технической, но, вероятно, выполнимой.
Основным преимуществом этого подхода является то, что он единственный, который не требует от вас изменения существующего кода приложения. Недостатком является то, что он не гарантированно работает; все еще возможно, что операция слияния не сможет объединить блок памяти, достаточно большой для выполнения запроса. Операция объединения может также вызвать значительные паузы в ответе приложения во время его выполнения.
Возможно, вам понадобится построить ваше приложение таким образом, чтобы структура данных была уплотнена. Это потребует от вас поддержки дескрипторов, которые поддерживают перемещаемые объекты, то есть механизм двойной косвенности. Я предполагаю, что, вероятно, существует одна или довольно небольшое количество различных структур данных, которые вызывают эту проблему фрагментации, поэтому может быть в состоянии локализовать любую работу по реструктуризации в вашем приложении.
Вариант 2: PAE
Windows поддерживает средства для непосредственного управления MMU, и есть несколько возможностей, которые могут применяться к вашему приложению. Это определенно потребует явной архитектурной поддержки от вашего приложения, но предлагает возможность использования пула памяти, который намного больше, чем 2 ГБ.
В серверных версиях Windows посмотрите на PAE , который поддерживается API , которые позволяют вам вручную манипулировать системным MMU и повторно отображать фрагменты памяти. Это может быть полезным для вас одним из двух способов
Вы можете построить менеджер для структуры данных таким образом, чтобы использовать этот механизм как неотъемлемую часть управления данными.
Если вы можете подогнать элементы в вашей структуре данных к границам страниц, вы можете использовать это как способ консолидации памяти.
Однако этот подход потребует от вас реинжиниринга приложения, чтобы ссылки на объекты имели достаточно информации для управления явным процессом замены (возможно, какой-то менеджер наложений с механизмом прокси для объектов, на которые ссылается эта система ). Это означает, что любое решение, включающее PAE, не является заменой FastMM - вам придется изменить приложение, чтобы явно поддерживать PAE.
Однако механизм прокси такого рода может означать, что эта подсистема может быть относительно прозрачной для клиентов. Помимо накладных расходов на управление косвенным обращением и оверлеями (что может или не может быть существенной проблемой), прокси могут быть практически неотличимы от исходного API. Этот тип подхода лучше всего подойдет для относительно небольшого числа больших и тяжеловесных объектов с минимальным присоединением - каноническим приложением для этого является кэширование на диске. Прокси-серверы должны были бы оставаться в фиксированном месте в памяти, чтобы к более крупным объектам обращались через механизм наложения. YMMV.
Вариант 3. Исправить проблему в источнике
Одна из возможностей состоит в том, что ваша стратегия размещения объектов может быть оптимизирована из кода приложения (возможно, из пулов объектов, распределенных навалом и затем управляемых из приложения). Это может позволить вам разобраться с фрагментацией памяти внутри приложения, не пытаясь переписать диспетчер памяти.
Опять же, этот подход означает, что вам придется перестраивать части вашего приложения, и применимость этого подхода действительно зависит от природы вашего приложения. Только вы можете судить, насколько хорошо это может сработать.