2009-10-13 4 views
13

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

+2

Это скорее тема обсуждения, чем вопрос с реальным ответом; рассмотрите возможность переключения на вики. –

+0

Это, кажется, больше обсуждается с ответами, опубликованными до сих пор. На этот вопрос можно ответить либо «Концепция не полезная», либо «Концепция полезная и * вот пример того, как». «Концепция полезная» без конкретного примера на самом деле не отвечает на вопрос. – sylvanaar

+0

см. Этот пост рассказывает о стеке и куче.Чистая http://stackoverflow.com/questions/12727821/net-stack-and-heap-what-goes-where-when-i-declare-a-string/12728239#12728239 – DRobertE

ответ

12

Для меня это разница между «разработчиком/программистом» и «мастером».Любой может научиться писать код и видеть, как вещи «магически происходят» для вас, не зная, почему и как. Чтобы действительно быть ценным в том, что вы делаете, я думаю, что очень важно узнать как можно больше о Framework, который вы используете. Помните, что это не только язык , это основа, в которой вы используете лучшее приложение для своих способностей.

Я проанализировал много дампов памяти за эти годы и нашел его чрезвычайно полезным, зная внутренности и различия между ними. Большинство из них были условиями OutOfMemory и нестабильными приложениями. Это знание абсолютно необходимо использовать WinDbg при просмотре дампов. При исследовании дампа памяти, зная, как распределена память между процессом ядра/пользовательского режима и CLR, вы можете по крайней мере сообщить вам, с чего начать анализ.

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

Там около 8 различных куч, которые используют CLR:

  1. Loader Heap: содержит CLR структуру и систему типа
  2. Высокочастотного Heap: статика, MethodTables, FieldDescs, интерфейс карта
  3. Low Frequency Куча: таблицы EEClass, ClassLoader и таблицы поиска
  4. Куча кусков: заглушки для CAS, COM-обертки, P/Invoke
  5. Большая куча объектов: выделение памяти, требующее более 85k байтов
  6. GC Heap: пользователь выделил кучу память приватной для приложения
  7. JIT Code Heap: память, выделенная mscoreee (Execution Engine) и JIT компилятора для управляемого кода
  8. процесс/Base Heap: Interop/неуправляемые ассигнования, родные памяти и т.д.

В поисках того, что куча имеет высокие распределения могут сказать мне, если у меня есть фрагментация памяти, утечка памяти, управляемые Interop/неуправляемые утечки и т.д.

Зная, что у вас есть 1 Мбайты (на x86)/4MB (на x64) пространства стека, выделенного для каждого потока tha t ваше приложение напоминает, что если у меня есть 100 потоков, у вас будет дополнительно 100 МБ использования виртуальной памяти.

У меня был клиент, у которого были проблемы с проблемами с сервером Citrix с проблемами OutOfMemory, которые были нестабильны и медленны, когда их приложение запускалось на нем в нескольких сеансах. Посмотрев на дамп (у меня не было доступа к серверу), я увидел, что в этом экземпляре приложения используется более 700 потоков! Знание распределения стека потоков позволило мне сопоставить OOM, вызванные использованием высоких потоков.

Одним словом, из-за того, что я делаю для своей «роли», это бесценное знание. Конечно, даже если вы не отлаживаете свалки памяти, это никогда не повредит!

+0

Я просто хотел бы добавить для полноты: хотя каждый поток имеет стек по умолчанию 1 MiB, это не означает, что память совершена (это не так, по крайней мере, не в 64-разрядной Windows 7 с .NET рамки 4). Значения по умолчанию, которые я видел, больше похожи на 4 kiB по умолчанию. Таким образом, требуется 1 MiB виртуального адресного пространства, но не 1 MiB физической памяти (будь то файл страницы, другой файл с отображением памяти или реальная оперативная память). В 64-битной системе вы можете иметь тысячи стеков и все равно брать всего лишь несколько мегабайт «реальной» памяти. Фактически, я видел, что управляемая куча выделяет TiBs, а только совершает несколько мегабайт. – Luaan

+0

Благодарим вас, что нужно уточнить. Я отредактировал свой ответ, чтобы явным образом вызывать виртуальную память вместо Committed. –

3

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

Я считаю, что очень важно понять, как использовать платформу .NET (и большинство других языков). Я никогда не нанимаю кого-то, у кого нет четкого понимания использования памяти в стеке против кучи.

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

+3

Я согласен с вами, но вы действительно не представили хороший пример того, что нужно знать о стеке и куче. Мне интересно узнать что-то новое :) –

+5

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

+0

Ну, я обычно спрашиваю в общих чертах и ​​стараюсь, чтобы кандидат объяснил мне разницу. Это стало одним из моих ориентиров на уровне понимания - я чувствую, что кто-то, кто знает, как распределяется память в .NET, по крайней мере будет желать и способен узнать все, что требуется. Я думаю, вам нужно понять: 1) Стек, в общих чертах, 2) Куча, в общих чертах, 3) Как работают ссылочные типы, 4) Как работают типы значений, 5) Прохождение аргумента с использованием ref/out и как это отличается от значения, особенно со ссылочными типами (не стек/куча, но полусвязанный) –

16

Различие в .NET между семантикой ссылочных типов и типов значений является гораздо более важной концепцией для понимания.

Лично я никогда не думал о стеке или куче за все мои годы кодирования (только на основе CLR).

+1

mmm - Трудно понять ссылочный тип и семантику типа значения (особенно, почему за ними), не понимая стек и кучу. –

+0

Возможно, лучший вопрос: «Объясните, почему значение :: reference! = Stack :: heap». :) –

+0

Jon Skeet уже ответил на этот вопрос http://www.yoda.arachsys.com/csharp/memory.html – MarkJ

4

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

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

11

Конечно, полезно понимать различие при создании компиляторов.

Вот несколько статей я написал о том, как различные вопросы в воздействии управления памятью при разработке и осуществлении на языке С # и CLR:

http://blogs.msdn.com/ericlippert/archive/tags/Memory+Management/default.aspx

0

Важное различие между ссылочными типами и типы значений. Неверно, что «типы значений идут в стек, ссылочные типы переходят в кучу». Джон Скит написал about this и поэтому имеет Eric Lippert.

0

У нас был объект претензии (бизнес-объект), который содержал данные для целого требования. Одним из требований приложения было создание контрольного журнала для каждого значения, измененного пользователем. Для этого, не дважды попав в базу данных, мы будем поддерживать оригинальную структуру заявки в форме и объекте «Искрочный запрос». Объект «Рабочая реклама» будет обновляться, когда пользователь щелкнет «Сохранить», и затем мы сравним свойства Original Entity Entity с соответствующими свойствами Entity Entity Entity, чтобы определить, что изменилось. Однажды мы заметили, что наш метод сравнения никогда не находит разницы. Именно здесь мое понимание стека и кучи спасло мой задний конец (в частности, типы значений по сравнению с ссылочными типами). Потому что нам нужно поддерживать на копии одного и того же объекта в памяти разработчик просто создал два объекта

Dim originalClaim As ClaimBE 
Dim workingClaim As ClaimBE 

затем называется методом бизнес-слоя, чтобы вернуть объект претензии и назначается тот же claimBE к обеим переменным

originalClaim = BLL.GetClaim() 
workingClaim = originalClaim 

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

+1

Ваша история не имеет ничего общего делать стек против кучи; это только значение по сравнению с ссылкой. Как указывали другие, типы значений имеют различие в том, что они могут храниться в стеке, но это то, где отношения заканчиваются. Будут ли 'originalClaim' и' workClaim' храниться в стеке, или куча не имеет отношения к вашей истории. – Gabe

+0

@Gabe Еще смешнее, ссылочные типы могут также идти на стек. Это случается не часто (одним примером является ключевое слово 'stackalloc' в небезопасном контексте), но это может измениться в будущих версиях .NET, если это когда-либо сочтет это проблемой - это будет огромной помощью при выполнении больших операций переноса, используйте выделенные объекты внутри данной области - не нужно помещать это в кучу для сбора GC позже, просто используйте стек, нажмите, поп, сделайте, не нужен GC. – Luaan

Смежные вопросы