DLL перезагружаются на предпочитаемый адрес

В Windows Server 2003 мое приложение начало долго загружаться при новой установке. Подозревая, что библиотеки DLL не загружаются по своему предпочтительному адресу, и это занимает некоторое время (приложение имеет более 100 библиотек DLL, включая сторонние), я запустил утилиту sysinternals listDLLs, попросив ее отметить каждую перемещенную dll. Как ни странно, для большинства DLL в списке я получаю что-то вроде этого:

Base        Size      Path
  ### Relocated from base of 0x44e90000:
0x44e90000  0x39000   validation.dll

То есть: они помечены как перемещенные (и время загрузки определенно подтверждает эту теорию), но их адрес загрузки остается предпочтительным адресом.

Некоторые сторонние библиотеки DLL, кажется, невосприимчивы к этому, но в целом это происходит примерно с 90% библиотек DLL, загружаемых приложением.

В Windows 7 кажется, что единственные помеченные библиотеки DLL — это те, которые действительно перемещаются, и время загрузки (как и ожидалось) значительно быстрее.

Чем это вызвано? Как я могу это остановить?

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


person whtstar2    schedule 04.12.2013    source источник


Ответы (1)


Это очень распространено, установка параметра компоновщика /BASE часто упускается из виду, а его поддержка при увеличении размера DLL становится неприятной задачей обслуживания. Это не очень хорошо повторяется между версиями операционной системы, они загружают разные библиотеки DLL раньше вашей, и это может привести к перемещению на одной, но не на другой. Кроме того, однократное перемещение может привести к череде принудительных перемещений всех последующих библиотек DLL.

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

Гораздо более распространенной проблемой во времени загрузки является скорость дисковода. Проблема, когда у вас много DLL, они должны быть расположены на диске при холодном запуске. Со 100 DLL это может стоить 5 секунд. Вы должны заподозрить проблему с холодным запуском, если вы не видите задержки, когда завершаете программу и запускаете ее снова. Это хорошее начало, библиотеки DLL уже присутствуют в кеше файловой системы, поэтому их не нужно искать снова. Решение проблемы с холодным запуском требует более качественного оборудования, твердотельные накопители хороши. Или машина изучает ваш шаблон использования, чтобы SuperFetch предварительно извлекала для вас библиотеки DLL перед запуском программы.

Во всяком случае, если вы подозреваете проблему с перемещением, вам нужно создать собственную карту памяти, чтобы найти хорошие базовые адреса, которые не вызывают перемещение. Вам нужна хорошая отправная точка, зная порядок загрузки и размеры DLL. Вы получаете это, скажем, от отладчика VS. Окно вывода показывает порядок загрузки, окно Debug + Windows + Modules показывает размеры DLL. Компоновщик поддерживает указание файла .txt для базовых адресов в параметре /BASE, лучший способ сделать это, чтобы вам не приходилось постоянно возиться с отдельным значением /BASE, пока ваш код продолжает расти.

person Hans Passant    schedule 04.12.2013
comment
Мы указали базовые адреса для всех наших dll. Кроме того, одно перемещение может привести к череде принудительных перемещений всех последующих библиотек DLL. Вот именно: ни одна из них не перемещается по другому адресу — все они в их предпочтительный адрес, если вы верите в адрес загрузки Process Explorer (и базу в выводе listDLLs выше). Что-то занимает много времени, и dll помечаются как перебазированные, но все они находятся в том месте, где мы их просили... - person whtstar2; 04.12.2013
comment
Что ж, хорошо, мир имеет смысл. Очевидно, теперь вы будете гораздо больше заинтересованы в решении гораздо более распространенной проблемы, которую я задокументировал. Используйте настоящий отладчик, чтобы отследить ненадежное предупреждение о перемещении. - person Hans Passant; 04.12.2013