C # vb: System.Func занимает сколько памяти? - PullRequest
6 голосов
/ 23 апреля 2011

сколько именно памяти занимает System.Func?

Есть ли разница, если System.Func равен 1 или 1000 строкам?

Ответы [ 4 ]

12 голосов
/ 23 апреля 2011

Func <> - это тип делегата, экземпляр занимает 32 байта памяти в джиттере x86:

  • 8 байт для заголовка объекта
  • 4 байта для поля Delegate._methodBase
  • 4 байта для поля Delegate._methodPtr
  • 4 байта для поля Delegate._methodPtrAux
  • 4 байта для поля Delegate._target
  • 4 байта для поля MulticastDelegate._invocationCount
  • 4 байта для поля MulticastDelegate._invocationList

Размер целевого метода не имеет значения, объект делегата хранит только адрес метода.

7 голосов
/ 23 апреля 2011

На этот вопрос есть ответы на многих уровнях, и я боюсь, что вы не получите действительно 100% точный, но здесь идет.

Здесь есть две разные части памяти, на которых я хочу сосредоточиться:

  1. Память, выделенная для хранения кода
  2. Память, выделенная на код

Первый фрагмент выделяется JITter, и это определенно связано с количеством кода в методе. Однако, если вы решите распространить этот метод на несколько методов (что следует делать, метод не должен быть длиной в тысячу строк, не говоря уже о 50), то вы также распределите память по этим методам. На самом деле, вероятно, существует определенное количество служебных данных для каждого метода, поэтому в этом случае может оказаться, что для кода JITted будет использовано больше памяти, если вы будете использовать больше методов, чем один большой, но это не имеет значения. Разделите это. Серьезно.

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

Кроме того, в сборке режима выпуска, работающей вне отладчика, сборщик мусора очень агрессивен, поэтому переменная, объявленная в верхней части метода, заполненная структурой данных, а затем в методе не используется больше GC может потребовать это, так как он имеет вид с высоты птичьего полета вашего кода. Он может «видеть», что переменная больше не используется, поэтому можно просто собрать все, что в ней есть.

Однако во время отладки срок жизни этой переменной искусственно увеличивается до конца области действия / метода, поэтому, если вы остановите программу где-то в той части кода, где переменная больше не используется, вы можете еще осмотрите его содержимое.

Итак, подытожим:

  1. Более длинный метод, вероятно, потребует больше памяти JITted, чем более короткий метод, но если вы не можете фактически удалить код, в отличие от простого его перемещения и разделения, он не имеет значения. Пишите короткие методы.
  2. Память, выделенная методом, связана не с количеством строк, а с содержанием этих строк.

Теперь, что касается System.Func<T...>, это просто указатель на небольшой объект. Размер этого объекта будет зависеть от количества аргументов (если я правильно помню) функции / метода, на которую он ссылается, но в остальном он не зависит от размера метода, кода или выделения памяти или чего-то еще.

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

Не беспокойтесь об использовании делегатов. Они довольно дешевы, как с точки зрения процессора, так и с точки зрения памяти.

3 голосов
/ 23 апреля 2011

System.Func - это просто делегат, который просто содержит список указателей на функции, поэтому объем памяти, занимаемый System.Func, является постоянным относительно количества назначенных ему делегатов функций независимо от размерафункции, на которые он фактически указывает.

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

1 голос
/ 23 апреля 2011

Я не знаю, насколько это помогает, но, используя это, мы можем узнать об использовании памяти процессом

int memory;
Process[] application;
application = Process.GetProcessesByName("MyApplication.exe");
applicationMemory = application[0].PrivateMemorySize;
Console.WriteLine("Memory used: {0}.", applicationMemory);

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

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