Заставить C # / .NET иметь небольшую площадь? - PullRequest
3 голосов
/ 27 ноября 2009

Я замечаю обычный большой объем памяти. Одно приложение, которое я написал, - это консольное приложение, которое использует <50 линий и просто загружает серию файлов исключительно с помощью WebRequest. Другое приложение, которое не является тривиальным (MySQL, DLS, многопоточность, список с 100 пунктов). Первый использует 21 МБ (debug, ide), другой использует 39 МБ (debug, ide). У меня также есть другое приложение, опрашивающее мой сайт (также использующее WebRequest) для обновления статуса, которое находится на моем трее и уведомляет меня, используя 26mbs (выпуск, не проходил через ide). </p>

Почему они такие высокие? я знаю, что написал приложение для C ++ выше, используя curl, который работал <2mb, и мой самый большой C ++ prj - 11mb, который загружает в dll по 100 КБ и в двоичный файл по 200 КБ (используя directx с иконками и звуком win32). Как я могу скомпилировать мой код C #, чтобы он был более дружественным к пространству. Я хотел бы развернуть их на сервере, который может иметь только 128 или 256 МБ оперативной памяти, и некоторые из этих приложений убьют его. </p>

Примечание к сайту: я запустил первое упомянутое приложение (консоль DLer) в режиме релиза (и через ide), и оно подскочило до 32 МБ. Зачем!?! это более запутанно.

Ответы [ 4 ]

5 голосов
/ 27 ноября 2009

Честно говоря, не беспокойтесь о следе управляемого кода, пока вы не сможете измерить случаи, когда его объем памяти создает проблемы. При запуске сборки .NET CLR делает много разных вещей, слишком много, чтобы перечислять здесь, но см. http://weblogs.asp.net/pwilson/archive/2004/02/14/73033.aspx, а для других ресурсов см. http://geekswithblogs.net/sdorman/archive/2008/09/14/.net-memory-management-ndash-resources.aspx

Взгляните на эту статью, чтобы узнать, как вы можете определить, что ваше приложение действительно использует с точки зрения памяти, потому что диспетчер задач не показывает реальную историю http://www.codinghorror.com/blog/archives/000271.html

Если вы действительно хотите, чтобы ваша сборка отображалась в диспетчере задач с меньшим объемом памяти, чем нужно, чтобы отбросить управляемый код. Один из способов обмана - скомпилировать ваше приложение, используя что-то вроде Salamander Protector , что делает ваше приложение исполняемым, а не сборкой .NET.

3 голосов
/ 27 ноября 2009

Небольшие .NET-приложения не могут реально конкурировать с приложениями на C / C ++ по размеру памяти.

.NET. Время выполнения огромно по сравнению с тем, что нужно нативному приложению для запуска. Чтобы запустить приложение .NET, CLR должен быть в памяти. Он должен не только загружать такие компоненты, как JIT-компилятор, GC и т. Д., Он также требует ряда внутренних структур данных. Например. даже самое простое приложение .NET имеет три домена приложений, два из которых используются внутри среды CLR, а одно - для самого приложения.

Кроме того, сборки загружаются при обращении к ним. Даже если методы не объединяются до тех пор, пока они не понадобятся, сама сборка при загрузке использует много адресного пространства. Когда код соединяется в какой-то момент, он снова сохраняется в памяти как собственный код. Таким образом, по существу скомпилированный код присутствует дважды в приложении .NET.

Наконец, система типов намного сложнее в .NET по сравнению с тем, что вы найдете в приложении C / C ++. Каждый отдельный объект несет информацию о своем типе. Это позволяет отражать и другие полезные функции, но это имеет свою цену.

Если вы хотите очень маленького размера, .NET может быть достаточно хорошим, но это, конечно, не самый очевидный выбор, поскольку вы будете платить за накладные расходы времени выполнения.

Также, пожалуйста, смотрите этот связанный вопрос Сокращение использования памяти приложениями .NET?

2 голосов
/ 27 ноября 2009

Я не эксперт по CLR, но я заметил, что CLR распределяет память по блокам и может очень сильно увеличиваться, даже если ваше приложение не использует столько памяти В некотором роде CLR любит удерживать память, которая ему не нужна, поэтому ему не нужно вызывать Windows для перераспределения.

Проверьте личные байты вашего приложения. Частные байты должны быть более разумным индикатором памяти, которую вы фактически используете, а не того, сколько удерживает CLR. Кроме того, установка MaxWorkingSet этого процесса, кажется, волшебным образом перекалибрует статистику в диспетчере задач.

System.Diagnostics.Process loProcess = System.Diagnostics.Process.GetCurrentProcess();
loProcess.MaxWorkingSet = loProcess.MaxWorkingSet;

Код выше выглядит как кандидат на TheDailyWtf. LOL

0 голосов
/ 27 ноября 2009

Следует помнить, что сборщик мусора не всегда освобождает память, пока это не понадобится кому-то еще. Поэтому, хотя ваше приложение может утверждать, что использует 100 МБ памяти, в действительности оно может использовать 50 МБ, но у сборщика мусора еще не было причины собирать и освобождать все остальное.

Даже базовая инициализация приложения создает много временных файлов, что заставляет CLR выделять блоки памяти для приложения. Пока в системе достаточно памяти, сборщик мусора будет лениво обнаруживать и очищать неиспользуемую память; это оптимизация скорости. Не беспокойтесь, когда вашей системе понадобится больше памяти, сборщик мусора начнет работать и начнет выполнять более глубокое сканирование.

Убедитесь, что вы не вызываете сборщик мусора вручную, чем чаще он вызывается, тем больше объектов передается в старшие поколения, которые не будут собираться до тех пор, пока в системе не будет мало памяти.

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