1

За эти годы мое приложение выросло с нескольких МБ до более чем 50 МБ. Чтобы упростить развертывание, я всегда придерживался одного файла EXE вместо меньшего EXE и большого количества DLL (см. Также мой вопрос по StackOverflow: https://stackoverflow.com/questions/2881296/one-big-executable-or- много-мало-dll).

Тем не менее, теперь у меня есть клиенты, которые жалуются, что у каждой новой версии повышенные требования к памяти. Переход к DLL может решить некоторые из этих проблем, потому что я думаю, что Windows загружает DLL только один раз в память (поэтому, если у вас есть 50 процессов, использующих одну и ту же DLL, DLL занимает место в физической памяти только один раз).

С другой стороны, если у меня 50 процессов, использующих один и тот же EXE-файл, я ожидаю, что Windows также совместно использует этот EXE-файл для нескольких процессов. Но у меня сложилось впечатление, что Windows не делает этого (а делает это только для DLL-файлов). Это наблюдение верно?

Действительно ли Windows загружает DLL один раз в память, если она используется несколькими процессами?

Windows также загружает файл EXE один раз в память, если используется несколькими процессами? Или нет?

2 ответа2

2

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

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

2

Код DLL и EXE является абсолютно общим - в ОЗУ имеется только одна копия кода, независимо от того, сколько процессов используют EXE или библиотеки DLL. (И, конечно, не весь код обязательно будет в ОЗУ - только тот, на который недавно ссылались.)

DLL и EXE являются примерами сопоставленных файлов. Сопоставленные файлы вносят вклад в общее виртуальное адресное пространство процесса. Они не вносят вклад в "частные байты" или "выделенную" память (одно и то же, но разные утилиты используют разные термины).

Процессы сами по себе не имеют стеков. Нити имеют стеки. (Можно сказать, что процесс только с одним потоком имеет стек "a" для этого процесса, но на самом деле стек является атрибутом потока, а не процесса.) Но DLL не "загружаются в стеке процессов" (ни в стеке потоков в этом отношении). Библиотеки DLL и EXE отображаются в разделяемом, а не частном виртуальном адресном пространстве процесса. Это правда, что это делается для каждого процесса, использующего DLL или EXE, но эти несколько экземпляров предназначены для сопоставлений виртуальной памяти. Поскольку это виртуальное адресное пространство общего пользования, в ОЗУ осталась только одна копия кода.

Стеки потоков, наряду с кучами (которые являются общими для всего процесса) и статическим хранилищем, также отображаются в области процессов, но, в отличие от отображенной памяти, являются частными для каждого процесса.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .