Приложения .NET естественно занимают много памяти? - PullRequest
5 голосов
/ 09 октября 2009

Впервые в жизни я начал писать большое приложение на C #. Я написал пример модуля для проверки идеи моего программного обеспечения. Этот модуль содержал несколько десятков словарей C # и списки объектов, каждый из которых имел несколько членов и свойств.

Я был шокирован тем, что после инициализации основных объектов он в конечном итоге использует около 40 МБ ОЗУ.

Я протестировал и обнаружил, что после инициализации объекта выделяется более 30 МБ, но у меня сложилось впечатление, что, учитывая размер моих объектов, нужно было бы использовать не более нескольких сотен килобайт.

Я что-то сделал не так, или .NET требует много памяти по сравнению с приложениями с собственным кодом?

Ответы [ 8 ]

12 голосов
/ 09 октября 2009

Как вы определили, сколько памяти было использовано? Известно, что приложения .NET охотно резервируют больше памяти, чем им нужно, при условии, что доступно достаточно памяти, и высвобождают память обратно в систему, если она начинает исчерпывать память.

Я думаю, вы можете получить некоторые указатели в этой статье MSDN .

7 голосов
/ 09 октября 2009

Использование диспетчера задач для проверки использования памяти может быть ужасно неточным.

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

Виды вещей, которые я видел в своем собственном коде, включают

  • Недооценка того, сколько памяти я на самом деле использую (не считая отдельные объекты должным образом, не допуская, чтобы списки имели «запасную» емкость)
  • Хранение ссылок на временные объекты, которые мне не нужны
  • Не допускается создание временных объектов, созданных во время операции, которые еще не были собраны сборщиком мусора
  • Не учитывает нераспределенную память - память, которая была востребована из ОС (и, следовательно, отображается как часть процесса в диспетчере задач), но еще не была выделена ни одному объекту
  • Не допускается использование стеков потоков (каждый поток получает свой собственный стек; приложения .NET всегда многопоточные, так как среда может создавать несколько собственных потоков).
5 голосов
/ 09 октября 2009

В те дни, когда у нас есть несколько ГБ ОЗУ на машине, идея о том, что приложение, ориентированное на пользователя, как вы обычно создаете в C #, должна использовать только несколько 100 КБ оперативной памяти, является обратной. Любой неиспользованный оперативной памяти в вашей системе тратится впустую.

Имея это в виду, C # выделяет память, используя стратегию, совершенно отличную от C ++, так что более крупные порции выделяются и освобождаются реже.

Тем не менее, 40 кажется немного высоким. Я привык к чему-то ближе к 10-14Мб для очень простых консольных приложений. Может быть, есть форма, принимающая оперативную память, или, может быть, я использую другую версию фреймворка (2.0).

2 голосов
/ 09 октября 2009

Я бы сказал, что если у вас нет очень веской причины беспокоиться об использовании ОЗУ, нет. Как и при оптимизации, вы должны оптимизировать только там, где есть клиент / конечный пользователь должен сделать это. Я не верю, что в наши дни пользователи настолько ограничены памятью (если вы не говорите о встроенной системе), что они собираются заметить или беспокоиться о пропущенных 38 МБ.

2 голосов
/ 09 октября 2009

Среда выполнения .Net имеет определенные большие накладные расходы - мы обнаружили, что даже простые приложения будут иметь тенденцию использовать гораздо больше памяти, чем аналогичные приложения, написанные на C ++. К счастью, эти издержки быстро исчезают из-за увеличения размера кода. Второй фактор - это сборщик мусора, сборщик мусора запускается «всякий раз», поэтому, по сравнению с C ++, выделение памяти обычно освобождается не сразу, а, когда это необходимо.

2 голосов
/ 09 октября 2009

Это не всегда о языке, обычно о том, как он используется.

Хороший код может эффективно использовать память на любом языке.

Неверный код неэффективно использует память на каждом языке

0 голосов
/ 09 октября 2009

Если вы используете диспетчер задач для просмотра памяти, это может ввести в заблуждение. Рабочий набор - это количество виртуальной памяти, сопоставленной процессу. Не обязательно, сколько использует ваше приложение - это особенно верно в среде .NET для сбора мусора. Поскольку ваша программа выделяет память, .NET CLR / GC обычно запрашивает у ОС больше памяти, чем фактически требуется, чтобы в будущем она могла эффективно распределить эту память для управляемых объектов в вашей программе.

Быстрый и грязный способ (очень грязный), чтобы увидеть, влияет ли это на вас, - установить для свойства Process.MaxWorkingSet значение 0. Это похоже на использование SetProcessWorkingSetSize в Win32 попробуйте урезать количество страниц, отображаемых в процессе. Если вы сразу видите падение использования памяти, то вы знаете, что происходит. Однако, как только вы снова начнете выделять память через GC / CLR, она снова начнет работать - и обычно это хорошо. На самом деле вам не следует об этом беспокоиться и дать GC шанс сделать это правильно.

Чтобы оптимизировать использование памяти вашей программой и получить лучшее представление о том, как работает распределение памяти в CLR, я предлагаю вам начать возиться с dotTrace (мои предпочтения), Ants Profiler ( кто кстати публикует классное видео на эту тему тут ). CLRProfiler тоже интересен, но он немного устарел в наши дни, но он бесплатный.

0 голосов
/ 09 октября 2009

Выполняя быстрый расчет, вы, вероятно, выделяете около 340 КБ объектов (вычитая обычный удар c12MB для одиночных консольных приложений на 32-битной версии, как Стив!) И видите [удаление ссылки на типичный сценарий, потребляющего 8 байт на объект + затем некоторые для других обычные подозреваемые] времени выполнения и потери System.Object для ссылочных типов по раздутой технологии времени исполнения @ Sun.com ..

Попробуйте и спроектируйте для типов значений / структур, если это вообще возможно ... если вы не можете, жестко, скажите своим пользователям не запускать более 10 приложений .NET, или их машина будет работать медленнее, чем C64. Если вам от этого легче, попробуйте WPF или Silverlight и почувствуйте штраф в 100 МБ за несколько кнопок и яркую анимацию.

(чувство подавленности)

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