Принуждение Windows загружать библиотеки DLL в такие места, чтобы память была минимально фрагментирована.

Моему приложению требуется много памяти и большая структура данных для выполнения своей работы. Часто приложению требуется больше 1 ГБ памяти, а в некоторых случаях моим клиентам действительно нужно использовать 64-разрядную версию приложения, потому что у них есть несколько гигабайт памяти.

Раньше я мог легко объяснить пользователю, что если объем используемой памяти достигал 1,6–1,7 ГБ, это означало, что «нехватка памяти» или ситуация действительно близка к «нехватке памяти», и что им необходимо уменьшить их память или перейти на 64-битную версию.

В прошлом году я заметил, что часто приложение использует только около 1 ГБ, прежде чем ему уже не хватит памяти. После некоторых исследований выяснилось, что причиной этой проблемы является фрагментация памяти. Я использовал VMMAP (служебную программу SysInternals), чтобы посмотреть на использование памяти моим приложением, и увидел что-то вроде этого: Address Space Fragmentation

Оранжевые области - это память, выделенная моим приложением. Фиолетовые области - это исполняемый код.

Как вы можете видеть в нижней половине изображения, фиолетовые области (которые являются библиотеками DLL) загружаются по разным адресам, что приводит к фрагментации моей памяти. На самом деле это не проблема, если у моего клиента мало данных, но если у моего клиента есть наборы данных, которые занимают более 1 ГБ, а части приложения требуется большой блок памяти (например,50 МБ), это может привести к сбою выделения памяти, что приведет к сбою моего приложения.

Большинство моих структур данных основаны на STL и часто не требуют больших участков непрерывной памяти, но в некоторых случаях (например, очень большие строки) действительно необходимо иметь непрерывный блок памяти. К сожалению, не всегда можно изменить код так, чтобы он не нуждался в таком непрерывном блоке памяти.

Вопросы следующие:

  • Как я могу повлиять на место, где DLL загружаются в память, без явного использования REBASE для всех DLL на компьютере клиента или без явной загрузки всех DLL.
  • Есть ли способ указать адреса загрузки DLL в вашем собственном файле манифеста приложения?
  • Или есть способ указать Windows (через файл манифеста?) Не разбрасывать DLL (я думаю, что это разброс называется ASLR).

Конечно, лучшее решение - это то, на которое я могу повлиять из файла манифеста моего приложения, поскольку я полагаюсь на автоматическую / динамическую загрузку DLL в Windows.

Мое приложение работает в смешанном режиме (управляемое + неуправляемое), хотя большая часть приложения неуправляема.

Есть предложения?

8
задан Arnon Zilca 14 March 2016 в 12:44
поделиться