Сборка мусора и производительностьGarbage Collection and Performance

В этом разделе описаны вопросы, связанные со сборкой мусора и использованием памяти.This topic describes issues related to garbage collection and memory usage. Здесь рассматриваются проблемы, относящиеся к управляемой куче, и объясняется, как свести к минимуму влияние сборки мусора на работу приложений.It addresses issues that pertain to the managed heap and explains how to minimize the effect of garbage collection on your applications. Для каждого аспекта приводятся ссылки на процедуры, которые можно использовать для анализа проблем.Each issue has links to procedures that you can use to investigate problems.

В этом разделе содержатся следующие подразделы.This topic contains the following sections:

Средства анализа производительностиPerformance Analysis Tools

В следующих разделах описываются средства, которые можно использовать для диагностики проблем с использованием памяти и сборкой мусора.The following sections describe the tools that are available for investigating memory usage and garbage collection issues. Эти средства используются в процедурах, описанных далее в этом разделе.The procedures provided later in this topic refer to these tools.

Счетчики памятиMemory Performance Counters

Счетчики производительности можно использовать для сбора данных производительности.You can use performance counters to gather performance data. Инструкции см. в разделе Профилирование среды выполнения.For instructions, see Runtime Profiling. Категория счетчиков производительности "Память CLR .NET" (как описано в разделе Счетчики производительности в .NET Framework) предоставляет сведения о сборщике мусора.The .NET CLR Memory category of performance counters, as described in Performance Counters in the .NET Framework, provides information about the garbage collector.

Отладка с помощью расширения SOSDebugging with SOS

Для проверки объектов в управляемой куче можно использовать отладчик Windows (WinDbg).You can use the Windows Debugger (WinDbg) to inspect objects on the managed heap.

Чтобы установить WinDbg, установите средства отладки для Windows со страницы скачивания средств отладки для Windows.To install WinDbg, install Debugging Tools for Windows from the Download Debugging Tools for Windows page.

События сборки мусора (трассировка событий Windows)Garbage Collection ETW Events

Трассировка событий Windows (ETW) — это система трассировки, дополняющая поддержку профилирования и отладки в .NET Framework.Event tracing for Windows (ETW) is a tracing system that supplements the profiling and debugging support provided by the .NET Framework. Начиная с .NET Framework 4, события ETW для сборки мусора собирают полезные сведения для анализа управляемой кучи с точки зрения статистики.Starting with the .NET Framework 4, garbage collection ETW events capture useful information for analyzing the managed heap from a statistical point of view. Например, событие GCStart_V1, которое вызывается перед началом сборки мусора, предоставляет следующие сведения:For example, the GCStart_V1 event, which is raised when a garbage collection is about to occur, provides the following information:

  • собираемое поколение объектов;Which generation of objects is being collected.

  • что активировало сборку мусора;What triggered the garbage collection.

  • тип сборки мусора (параллельная или непараллельная).Type of garbage collection (concurrent or not concurrent).

Ведение журнала событий трассировки событий Windows эффективно и не скрывает проблемы производительности, связанные со сборкой мусора.ETW event logging is efficient and will not mask any performance problems associated with garbage collection. Процесс может предоставлять свои собственные события вместе с событиями трассировки событий Windows.A process can provide its own events in conjunction with ETW events. При регистрации в журнале события приложения можно соотнести с событиями сборки мусора, чтобы определить, как и когда возникают проблемы кучи.When logged, both the application's events and the garbage collection events can be correlated to determine how and when heap problems occur. Например, серверное приложение может предоставлять события в начале и в конце запроса клиента.For example, a server application could provide events at the start and end of a client request.

API профилированияThe Profiling API

Интерфейсы профилирования среды выполнения (CLR) предоставляют подробные сведения об объектах, которые были затронуты во время сборки мусора.The common language runtime (CLR) profiling interfaces provide detailed information about the objects that were affected during garbage collection. Профилировщик может получать уведомления о начале и завершении сборки мусора.A profiler can be notified when a garbage collection starts and ends. Он может предоставлять отчеты об объектах в управляемой куче, включая идентификацию объектов в каждом поколении.It can provide reports about the objects on the managed heap, including an identification of objects in each generation. Дополнительные сведения см. в разделе Общие сведения о профилировании.For more information, see Profiling Overview.

Профилировщики могут предоставлять исчерпывающую информацию.Profilers can provide comprehensive information. Однако сложные профилировщики потенциально могут менять поведение приложения.However, complex profilers can potentially modify an application's behavior.

Отслеживание ресурсов домена приложенияApplication Domain Resource Monitoring

Начиная с .NET Framework 4 функция отслеживания ресурсов домена приложения (ARM) позволяет узлам отслеживать загрузку ЦП и использование памяти доменом приложения.Starting with the .NET Framework 4, Application domain resource monitoring (ARM) enables hosts to monitor CPU and memory usage by application domain. Дополнительные сведения см. в разделе Отслеживание ресурсов домена приложения.For more information, see Application Domain Resource Monitoring.

К началуBack to top

Диагностика проблем производительностиTroubleshooting Performance Issues

Первый этап — определить, действительно ли проблема относится к сборке мусора.The first step is to determine whether the issue is actually garbage collection. Если это так, выберите одну из проблем в списке ниже, чтобы определить способ ее устранения.If you determine that it is, select from the following list to troubleshoot the problem.

Проблема Создается исключение нехватки памятиIssue: An Out-of-Memory Exception Is Thrown

Существует два допустимых случая создания управляемого исключения OutOfMemoryException:There are two legitimate cases for a managed OutOfMemoryException to be thrown:

  • нехватка виртуальной памяти;Running out of virtual memory.

    Сборщик мусора распределяет память из системы в виде сегментов заранее заданного размера.The garbage collector allocates memory from the system in segments of a pre-determined size. Если выделению требуется дополнительный сегмент, но в пространстве виртуальной памяти процесса не осталось непрерывных свободных блоков, произойдет сбой выделения памяти для управляемой кучи.If an allocation requires an additional segment, but there is no contiguous free block left in the process's virtual memory space, the allocation for the managed heap will fail.

  • нехватка физической памяти для выделения.Not having enough physical memory to allocate.

Проверки производительностиPerformance checks
Определите, является ли исключение нехватки памяти управляемым.Determine whether the out-of-memory exception is managed.

Определите, сколько виртуальной памяти можно зарезервировать.Determine how much virtual memory can be reserved.

Определите, имеется ли достаточный объем физической памяти.Determine whether there is enough physical memory.

Если выяснилось, что исключение не относится к допустимым сценариям, обратитесь в службу технической поддержки Майкрософт, сообщив следующие сведения:If you determine that the exception is not legitimate, contact Microsoft Customer Service and Support with the following information:

  • стек с управляемым исключением нехватки памяти,The stack with the managed out-of-memory exception.

  • полный дамп памяти,Full memory dump.

  • данные, подтверждающие недопустимый характер исключения нехватки памяти, включая данные, показывающие, что проблема не связана с виртуальной или физической памятью.Data that proves that it is not a legitimate out-of-memory exception, including data that shows that virtual or physical memory is not an issue.

Проблема Процесс использует слишком много памятиIssue: The Process Uses Too Much Memory

Считается, что с помощью индикатора использования памяти на вкладке Быстродействие диспетчера задач Windows можно определить, что процесс использует слишком много памяти.A common assumption is that the memory usage display on the Performance tab of Windows Task Manager can indicate when too much memory is being used. Однако этот индикатор относится к рабочему набору; он не предоставляет сведения об использовании виртуальной памяти.However, that display pertains to the working set; it does not provide information about virtual memory usage.

Если выяснилось, что проблема вызвана управляемой кучей, необходимо провести для управляемой кучи измерения в динамике, чтобы определить наличие каких-либо шаблонов.If you determine that the issue is caused by the managed heap, you must measure the managed heap over time to determine any patterns.

Если выяснилось, что проблема не вызвана управляемой кучей, необходимо использовать отладку неуправляемого кода.If you determine that the problem is not caused by the managed heap, you must use native debugging.

Проверки производительностиPerformance checks
Определите, сколько виртуальной памяти можно зарезервировать.Determine how much virtual memory can be reserved.

Определите объем памяти, зафиксированный управляемой кучей.Determine how much memory the managed heap is committing.

Определите объем памяти, зарезервированный управляемой кучей.Determine how much memory the managed heap reserves.

Определите большие объекты в поколении 2.Determine large objects in generation 2.

Определите ссылки на объекты.Determine references to objects.

Проблема Сборщик мусора недостаточно быстро освобождает объектыIssue: The Garbage Collector Does Not Reclaim Objects Fast Enough

Если есть признаки того, что объекты не освобождаются сборкой мусора должным образом, необходимо определить, нет ли строгих ссылок на эти объекты.When it appears as if objects are not being reclaimed as expected for garbage collection, you must determine if there are any strong references to those objects.

Эта проблема также может возникать, если не выполнялась сборка мусора для поколения, содержащего неиспользуемый объект. Это является признаком того, что для неиспользуемого объекта не выполнялся метод завершения.You may also encounter this issue if there has been no garbage collection for the generation that contains a dead object, which indicates that the finalizer for the dead object has not been run. Например, это может происходить, когда вы запускаете приложение однопотокового подразделения (STA) и не удается вызвать в него поток, который обслуживает очередь метода завершения.For example, this is possible when you are running a single-threaded apartment (STA) application and the thread that services the finalizer queue cannot call into it.

Проверки производительностиPerformance checks
Проверьте ссылки на объекты.Check references to objects.

Определите, выполнялся ли метод завершения.Determine whether a finalizer has been run.

Определите наличие объектов, ожидающих завершения.Determine whether there are objects waiting to be finalized.

Проблема Управляемая куча слишком сильно фрагментированаIssue: The Managed Heap Is Too fragmented

Уровень фрагментации рассчитывается как отношение свободного пространства ко всей выделенной памяти для поколения.The fragmentation level is calculated as the ratio of free space over the total allocated memory for the generation. Для поколения 2 допустимый уровень фрагментации составляет не более 20 %.For generation 2, an acceptable level of fragmentation is no more than 20%. Поскольку поколение 2 может очень сильно вырасти, показатель фрагментации более важен, чем абсолютное значение.Because generation 2 can get very big, the ratio of fragmentation is more important than the absolute value.

Наличие большого объема свободного пространства в поколении 0 не является проблемой, так как это поколение, в котором выделяются новые объекты.Having lots of free space in generation 0 is not a problem because this is the generation where new objects are allocated.

Фрагментация всегда возникает в куче больших объектов, так как для нее не выполняется сжатие.Fragmentation always occurs in the large object heap because it is not compacted. Смежные свободные объекты естественным образом свертываются в одно пространство для удовлетворения запросов на размещение больших объектов.Free objects that are adjacent are naturally collapsed into a single space to satisfy large object allocation requests.

Фрагментация может стать проблемой в поколении 1 и 2.Fragmentation can become a problem in generation 1 and generation 2. Если эти поколения имеют большой объем свободного места после сборки мусора, возможно, потребуется внести изменения в использование объекта приложения. Кроме того, может потребоваться пересмотреть время существования долгосрочных объектов.If these generations have a large amount of free space after a garbage collection, an application's object usage may need modification, and you should consider re-evaluating the lifetime of long-term objects.

Чрезмерное закрепление объектов может привести к увеличению фрагментации.Excessive pinning of objects can increase fragmentation. Если наблюдается высокая фрагментация, возможно, закреплено слишком много объектов.If fragmentation is high, too many objects could be pinned.

Если фрагментация виртуальной памяти препятствует добавлению сегментов сборщиком мусора, возможны следующие причины:If fragmentation of virtual memory is preventing the garbage collector from adding segments, the causes could be one of the following:

  • частая загрузка и выгрузка большого числа небольших сборок;Frequent loading and unloading of many small assemblies.

  • поддержание слишком большого числа ссылок на COM-объекты при взаимодействии с неуправляемым кодом;Holding too many references to COM objects when interoperating with unmanaged code.

  • создание больших временных объектов, что приводит к частому выделению и освобождению сегментов кучи больших объектов.Creation of large transient objects, which causes the large object heap to allocate and free heap segments frequently.

    При размещении среды CLR приложение может запросить сохранение сегментов сборщиком мусора.When hosting the CLR, an application can request that the garbage collector retain its segments. Это снижает частоту выделения сегментов.This reduces the frequency of segment allocations. Для этого необходимо использовать флаг STARTUP_HOARD_GC_VM в перечислении STARTUP_FLAGS.This is accomplished by using the STARTUP_HOARD_GC_VM flag in the STARTUP_FLAGS Enumeration.

Проверки производительностиPerformance checks
Определите объем свободного пространства в управляемой куче.Determine the amount of free space in the managed heap.

Определите количество закрепленных объектов.Determine the number of pinned objects.

Если вы считаете, что нет допустимых причин для фрагментации, обратитесь в службу технической поддержки Майкрософт.If you think that there is no legitimate cause for the fragmentation, contact Microsoft Customer Service and Support.

Проблема Слишком большие интервалы между сборками мусораIssue: Garbage Collection Pauses Are Too Long

Сборка мусора выполняется в режиме мягкого реального времени, поэтому приложение должно быть способно допускать определенные перерывы.Garbage collection operates in soft real time, so an application must be able to tolerate some pauses. Критерием мягкого реального времени является своевременное завершение 95 % операций.A criterion for soft real time is that 95% of the operations must finish on time.

В ходе параллельной сборки мусора управляемые потоки могут выполняться во время сборки, что означает крайне незначительные перерывы в работе.In concurrent garbage collection, managed threads are allowed to run during a collection, which means that pauses are very minimal.

Эфемерные сборки мусора (поколения 0 и 1) длятся лишь несколько миллисекунд, поэтому уменьшение перерывов обычно нецелесообразно.Ephemeral garbage collections (generations 0 and 1) last only a few milliseconds, so decreasing pauses is usually not feasible. Тем не менее, перерывы в сборках поколения 2 можно сократить, изменив шаблон обработки запросов приложения на выделение памяти.However, you can decrease the pauses in generation 2 collections by changing the pattern of allocation requests by an application.

Еще одним, более точным методом является использование событий трассировки ETW для сборки мусора.Another, more accurate, method is to use garbage collection ETW events. Затраты времени для сборок можно найти путем добавления разницы отметок времени для последовательности событий.You can find the timings for collections by adding the time stamp differences for a sequence of events. Вся последовательность сборки включает приостановку подсистемы выполнения, собственно сборку мусора и возобновление работы подсистемы выполнения.The whole collection sequence includes suspension of the execution engine, the garbage collection itself, and the resumption of the execution engine.

С помощью уведомлений сборки мусора можно определить, когда сервер приступает к сборке поколения 2. Кроме того, с их помощью можно определить, поможет ли маршрутизация запросов на другой сервер решить проблемы, связанные с задержками.You can use Garbage Collection Notifications to determine whether a server is about to have a generation 2 collection, and whether rerouting requests to another server could ease any problems with pauses.

Проверки производительностиPerformance checks
Определите продолжительность сборки мусора.Determine the length of time in a garbage collection.

Определите, что вызвало сборку мусора.Determine what caused a garbage collection.

Проблема Слишком большой размер поколения 0Issue: Generation 0 Is Too Big

Поколение 0 скорее всего имеет большое количество объектов в 64-разрядной системе, особенно если используется сборка мусора на сервере вместо сборки мусора на рабочей станции.Generation 0 is likely to have a larger number of objects on a 64-bit system, especially when you use server garbage collection instead of workstation garbage collection. Это происходит потому, что пороговое значение запуска сборки мусора для поколения 0 в таких средах выше и объемы сборки поколения 0 могут значительно увеличиваться.This is because the threshold to trigger a generation 0 garbage collection is higher in these environments, and generation 0 collections can get much bigger. Производительность повышается, если приложение выделяет больше памяти перед активацией сборки мусора.Performance is improved when an application allocates more memory before a garbage collection is triggered.

Проблема Слишком высокая загрузка ЦП во время сборки мусораIssue: CPU Usage During a Garbage Collection Is Too High

Во время сборки мусора загрузка ЦП будет высокой,CPU usage will be high during a garbage collection. если на сборку мусора тратится значительное время обработки, количество сборок слишком велико или сборка продолжается слишком долго.If a significant amount of process time is spent in a garbage collection, the number of collections is too frequent or the collection is lasting too long. Чем чаще выполняется выделение памяти для объектов в управляемой куче, тем чаще происходит сборка мусора.An increased allocation rate of objects on the managed heap causes garbage collection to occur more frequently. Уменьшение частоты выделения снижает частоту сборки мусора.Decreasing the allocation rate reduces the frequency of garbage collections.

Частоту выделения можно отслеживать с помощью счетчика производительности Allocated Bytes/second.You can monitor allocation rates by using the Allocated Bytes/second performance counter. Дополнительные сведения см. в разделе Счетчики производительности в .NET Framework.For more information, see Performance Counters in the .NET Framework.

Длительность сборки определяется в первую очередь количеством объектов, оставшихся после выделения.The duration of a collection is primarily a factor of the number of objects that survive after allocation. Сборщик мусора должен пройти большой объем памяти, если требуется выполнить сборку многих объектов.The garbage collector must go through a large amount of memory if many objects remain to be collected. Работа по сжатию оставшихся объектов занимает много времени.The work to compact the survivors is time-consuming. Чтобы определить, сколько объектов было обработано во время сборки, установите точку останова в отладчике в конце сборки мусора для заданного поколения.To determine how many objects were handled during a collection, set a breakpoint in the debugger at the end of a garbage collection for a specified generation.

Проверки производительностиPerformance checks
Определите, вызвана ли высокая загрузка ЦП сборкой мусора.Determine if high CPU usage is caused by garbage collection.

Задайте точку останова в конце сборки мусора.Set a breakpoint at the end of garbage collection.

К началуBack to top

Рекомендации по устранению неполадокTroubleshooting Guidelines

В этом разделе приводятся рекомендации, на которые следует опираться при проведении анализа.This section describes guidelines that you should consider as you begin your investigations.

Сборка мусора на сервере или рабочей станцииWorkstation or Server Garbage Collection

Убедитесь, что вы используете правильный тип сборки мусора.Determine if you are using the correct type of garbage collection. Если приложение использует несколько потоков и экземпляров объектов, используйте сборку мусора на сервере вместо сборки мусора на рабочей станции.If your application uses multiple threads and object instances, use server garbage collection instead of workstation garbage collection. Серверная сборка мусора обрабатывает несколько потоков, тогда как сборка мусора на рабочей станции требует, чтобы несколько экземпляров приложения выполняли собственные потоки сборки мусора, конкурируя за ресурсы процессора.Server garbage collection operates on multiple threads, whereas workstation garbage collection requires multiple instances of an application to run their own garbage collection threads and compete for CPU time.

Приложение с низкой нагрузкой, редко выполняющее задачи в фоновом режиме, например служба, может использовать сборку мусора на рабочей станции с отключенной параллельной сборкой мусора.An application that has a low load and that performs tasks infrequently in the background, such as a service, could use workstation garbage collection with concurrent garbage collection disabled.

Когда измерять размер управляемой кучиWhen to Measure the Managed Heap Size

Если вы не используете профилировщик, необходимо создать согласованный шаблон измерений для эффективной диагностики проблем с производительностью.Unless you are using a profiler, you will have to establish a consistent measuring pattern to effectively diagnose performance issues. При формировании расписания учтите следующие моменты.Consider the following points to establish a schedule:

  • Если измерение выполняется после сборки мусора поколения 2, вся куча будет свободна от мусора (неиспользуемых объектов).If you measure after a generation 2 garbage collection, the entire managed heap will be free of garbage (dead objects).

  • Если измерение выполняется сразу после сборки мусора поколения 0, объекты в поколении 1 и 2 еще не будут собраны.If you measure immediately after a generation 0 garbage collection, the objects in generations 1 and 2 will not be collected yet.

  • Если измерение выполняется сразу же перед сборкой мусора, будет измерено максимально возможное выделение до начала сборки мусора.If you measure immediately before a garbage collection, you will measure as much allocation as possible before the garbage collection starts.

  • Измерение во время сборки мусора проблематично, поскольку структуры данных сборщика мусора не находятся в допустимом состоянии для обхода и могут не предоставлять полные результаты.Measuring during a garbage collection is problematic, because the garbage collector data structures are not in a valid state for traversal and may not be able to give you the complete results. Это сделано намеренно.This is by design.

  • При использовании сборки мусора на рабочей станции с параллельной сборкой мусора освобожденные объекты не сжимаются, поэтому размер кучи может быть таким же или больше (из-за фрагментации размер может казаться больше).When you are using workstation garbage collection with concurrent garbage collection, the reclaimed objects are not compacted, so the heap size can be the same or larger (fragmentation can make it appear to be larger).

  • Параллельная сборка мусора для поколения 2 откладывается, если загрузка физической памяти слишком велика.Concurrent garbage collection on generation 2 is delayed when the physical memory load is too high.

Ниже приведена процедура задания точки останова для измерения управляемой кучи.The following procedure describes how to set a breakpoint so that you can measure the managed heap.

Задание точки останова в конце сборки мусораTo set a breakpoint at the end of garbage collection

  • В WinDbg с загруженным расширением отладчика SOS введите следующую команду:In WinDbg with the SOS debugger extension loaded, type the following command:

    bp mscorwks!WKS::GCHeap::RestartEE "j (dwo(mscorwks!WKS::GCHeap::GcCondemnedGeneration)==2) 'kb';'g'"bp mscorwks!WKS::GCHeap::RestartEE "j (dwo(mscorwks!WKS::GCHeap::GcCondemnedGeneration)==2) 'kb';'g'"

    Где GcCondemnedGeneration — желаемое поколение.where GcCondemnedGeneration is set to the desired generation. Команда требует закрытых символов.This command requires private symbols.

    Эта команда принудительно выполняет останов, если RestartEE выполняется после освобождения объектов поколения 2 для сборки мусора.This command forces a break if RestartEE is executed after generation 2 objects have been reclaimed for garbage collection.

    В серверной сборке мусора только один поток вызывает RestartEE, поэтому точка останова будет появляться только один раз во время сборки мусора поколения 2.In server garbage collection, only one thread calls RestartEE, so the breakpoint will occur only once during a generation 2 garbage collection.

К началуBack to top

Процедуры проверки производительностиPerformance Check Procedures

В этом разделе описаны следующие процедуры по выявлению причин проблем с производительностью.This section describes the following procedures to isolate the cause of your performance issue:

Чтобы определить, вызвана ли проблема сборкой мусора, выполните следующие действия.To determine whether the problem is caused by garbage collection

  • Проверьте следующие два счетчика производительности памяти:Examine the following two memory performance counters:

    • % времени в сборке мусора.% Time in GC. Отображение времени, потраченного на выполнение сборки мусора с момента последнего цикла сборки мусора (в процентах).Displays the percentage of elapsed time that was spent performing a garbage collection after the last garbage collection cycle. Этот счетчик используется, чтобы определить, тратит ли сборщик мусора слишком много времени на освобождение пространства в управляемой куче.Use this counter to determine whether the garbage collector is spending too much time to make managed heap space available. Если время, затраченное на сборку мусора, сравнительно мало, это может указывать на проблему ресурсов за пределами управляемой кучи.If the time spent in garbage collection is relatively low, that could indicate a resource problem outside the managed heap. Этот счетчик может предоставлять неточные данные при участии параллельной или фоновой сборки мусора.This counter may not be accurate when concurrent or background garbage collection is involved.

    • Всего зафиксировано байт.# Total committed Bytes. Отображение объема виртуальной памяти, в данный момент выделенной сборщиком мусора.Displays the amount of virtual memory currently committed by the garbage collector. С помощью этого счетчика можно определить, является ли память, используемая сборщиком мусора, избыточной частью памяти, которую использует приложение.Use this counter to determine whether the memory consumed by the garbage collector is an excessive portion of the memory that your application uses.

    Большинство счетчиков памяти обновляются в конце каждой сборки мусора.Most of the memory performance counters are updated at the end of each garbage collection. Таким образом, они могут не отражать текущие условия, сведения о которых вам требуются.Therefore, they may not reflect the current conditions that you want information about.

Чтобы определить, является ли исключение нехватки памяти управляемым, выполните следующие действия.To determine whether the out-of-memory exception is managed

  1. В отладчике Visual Studio или WinDbg с загруженным расширением отладчика SOS введите команду печати исключения (pe).In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the print exception (pe) command:

    !pe!pe

    Если исключение является управляемым, OutOfMemoryException отображается как тип исключения, как показано в следующем примере.If the exception is managed, OutOfMemoryException is displayed as the exception type, as shown in the following example.

    Exception object: 39594518
    Exception type: System.OutOfMemoryException
    Message: <none>
    InnerException: <none>
    StackTrace (generated):
    
  2. Если выходные данные не указывают на исключение, необходимо определить, к какому потоку относится исключение нехватки памяти.If the output does not specify an exception, you have to determine which thread the out-of-memory exception is from. Для вывода на экран всех потоков со стеками вызовов введите в отладчике следующую команду:Type the following command in the debugger to show all the threads with their call stacks:

    ~*kb~*kb

    Поток со стеком, для которого есть вызовы исключений, обозначается аргументом RaiseTheException.The thread with the stack that has exception calls is indicated by the RaiseTheException argument. Это объект управляемого исключения.This is the managed exception object.

    28adfb44 7923918f 5b61f2b4 00000000 5b61f2b4 mscorwks!RaiseTheException+0xa0
    
  3. Чтобы создать дамп вложенных исключений, можно использовать следующую команду.You can use the following command to dump nested exceptions.

    !pe -nested!pe -nested

    Если исключения не обнаружены, значит исключение нехватки памяти возникло в неуправляемом коде.If you do not find any exceptions, the out-of-memory exception originated from unmanaged code.

Чтобы определить, сколько виртуальной памяти можно зарезервировать, выполните следующие действия.To determine how much virtual memory can be reserved

  • В WinDbg с загруженным расширением отладчика SOS введите следующую команду, чтобы получить самую крупную свободную область:In WinDbg with the SOS debugger extension loaded, type the following command to get the largest free region:

    !address -summary!address -summary

    Самая крупная свободная область отображается, как показано в выходных данных команды ниже.The largest free region is displayed as shown in the following output.

    Largest free region: Base 54000000 - Size 0003A980
    

    В этом примере размер самой крупной свободной области составляет приблизительно 24 000 КБ (3A980 в шестнадцатеричном формате).In this example, the size of the largest free region is approximately 24000 KB (3A980 in hexadecimal). Эта область гораздо меньше, чем требуется сборщику мусора для сегмента.This region is much smaller than what the garbage collector needs for a segment.

    -или--or-

  • Используйте команду vmstat:Use the vmstat command:

    !vmstat!vmstat

    Самая крупная свободная область представлена самым большим значением в столбце MAXIMUM, как показано в следующих выходных данных.The largest free region is the largest value in the MAXIMUM column, as shown in the following output.

    TYPE        MINIMUM   MAXIMUM     AVERAGE   BLK COUNT   TOTAL
    ~~~~        ~~~~~~~   ~~~~~~~     ~~~~~~~   ~~~~~~~~~~  ~~~~
    Free:
    Small       8K        64K         46K       36          1,671K
    Medium      80K       864K        349K      3           1,047K
    Large       1,384K    1,278,848K  151,834K  12          1,822,015K
    Summary     8K        1,278,848K  35,779K   51          1,824,735K
    

Чтобы определить, имеется ли достаточный объем физической памяти, выполните следующие действия.To determine whether there is enough physical memory

  1. Запустите диспетчер задач Windows.Start Windows Task Manager.

  2. На вкладке Быстродействие обратите внимание на значение выделенной памяти.On the Performance tab, look at the committed value. (В Windows 7 это строка Выделено (КБ) в группе Система.)(In Windows 7, look at Commit (KB) in the System group.)

    Если значение в строке Всего близко к значению Ограничение, физической памяти не хватает.If the Total is close to the Limit, you are running low on physical memory.

Чтобы определить объем памяти, зафиксированный управляемой кучей, выполните следующие действия.To determine how much memory the managed heap is committing

  • Используйте счетчик производительности памяти # Total committed bytes, чтобы получить число байтов, фиксируемых управляемой кучей.Use the # Total committed bytes memory performance counter to get the number of bytes that the managed heap is committing. Сборщик мусора выделяет фрагменты в сегменте по мере необходимости, но не все одновременно.The garbage collector commits chunks on a segment as needed, not all at the same time.

    Примечание

    Не используйте счетчик производительности # Bytes in all Heaps, так как он не отражает фактическое использование памяти управляемой кучей.Do not use the # Bytes in all Heaps performance counter, because it does not represent actual memory usage by the managed heap. Размер поколения включается в это значение и, фактически, является его пороговым размером, то есть размером, который вызывает сборку мусора, если поколение заполнено объектами.The size of a generation is included in this value and is actually its threshold size, that is, the size that induces a garbage collection if the generation is filled with objects. Поэтому это значение обычно равно нулю.Therefore, this value is usually zero.

Чтобы определить объем памяти, зарезервированный управляемой кучей, выполните следующие действия.To determine how much memory the managed heap reserves

  • Используйте счетчик производительности памяти # Total reserved bytes.Use the # Total reserved bytes memory performance counter.

    Сборщик мусора резервирует память сегментами, и определить, где начинается сегмент, можно с помощью команды eeheap.The garbage collector reserves memory in segments, and you can determine where a segment starts by using the eeheap command.

    Важно!

    Хотя и можно определить объем памяти, выделяемой сборщиком мусора для каждого сегмента, размер сегмента зависит от реализации и может измениться в любое время, в том числе в ходе периодических обновлений.Although you can determine the amount of memory the garbage collector allocates for each segment, segment size is implementation-specific and is subject to change at any time, including in periodic updates. Приложение не должно делать никаких допущений относительно размера определенного сегмента, полагаться на него или пытаться настроить объем памяти, доступный для выделения сегментов.Your app should never make assumptions about or depend on a particular segment size, nor should it attempt to configure the amount of memory available for segment allocations.

  • В отладчике Visual Studio или WinDbg с загруженным расширением отладчика SOS введите следующую команду:In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the following command:

    !eeheap -gc!eeheap -gc

    Далее приведен результат.The result is as follows.

    Number of GC Heaps: 2
    ------------------------------
    Heap 0 (002db550)
    generation 0 starts at 0x02abe29c
    generation 1 starts at 0x02abdd08
    generation 2 starts at 0x02ab0038
    ephemeral segment allocation context: none
      segment    begin allocated     size
    02ab0000 02ab0038  02aceff4 0x0001efbc(126908)
    Large object heap starts at 0x0aab0038
      segment    begin allocated     size
    0aab0000 0aab0038  0aab2278 0x00002240(8768)
    Heap Size   0x211fc(135676)
    ------------------------------
    Heap 1 (002dc958)
    generation 0 starts at 0x06ab1bd8
    generation 1 starts at 0x06ab1bcc
    generation 2 starts at 0x06ab0038
    ephemeral segment allocation context: none
      segment    begin allocated     size
    06ab0000 06ab0038  06ab3be4 0x00003bac(15276)
    Large object heap starts at 0x0cab0038
      segment    begin allocated     size
    0cab0000 0cab0038  0cab0048 0x00000010(16)
    Heap Size    0x3bbc(15292)
    ------------------------------
    GC Heap Size   0x24db8(150968)
    

    Адреса с отметкой segment являются начальными адресами сегментов.The addresses indicated by "segment" are the starting addresses of the segments.

Чтобы определить большие объекты в поколении 2, выполните следующие действия.To determine large objects in generation 2

  • В отладчике Visual Studio или WinDbg с загруженным расширением отладчика SOS введите следующую команду:In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the following command:

    !dumpheap –stat!dumpheap –stat

    Если управляемая куча имеет большой размер, выполнение команды dumpheap может занять некоторое время.If the managed heap is big, dumpheap may take a while to finish.

    Вы можете начать анализ с последних нескольких строк вывода, поскольку в них перечислены объекты, занимающие наибольшее пространство.You can start analyzing from the last few lines of the output, because they list the objects that use the most space. Например:For example:

    2c6108d4   173712     14591808 DevExpress.XtraGrid.Views.Grid.ViewInfo.GridCellInfo
    00155f80      533     15216804      Free
    7a747c78   791070     15821400 System.Collections.Specialized.ListDictionary+DictionaryNode
    7a747bac   700930     19626040 System.Collections.Specialized.ListDictionary
    2c64e36c    78644     20762016 DevExpress.XtraEditors.ViewInfo.TextEditViewInfo
    79124228   121143     29064120 System.Object[]
    035f0ee4    81626     35588936 Toolkit.TlkOrder
    00fcae40     6193     44911636 WaveBasedStrategy.Tick_Snap[]
    791242ec    40182     90664128 System.Collections.Hashtable+bucket[]
    790fa3e0  3154024    137881448 System.String
    Total 8454945 objects
    

    Последний объект в списке является строкой и занимает больше всего места.The last object listed is a string and occupies the most space. Вы можете проанализировать приложение, чтобы понять, как можно оптимизировать строковые объекты.You can examine your application to see how your string objects can be optimized. Чтобы вывести на экран строки в диапазоне от 150 до 200 байтов, введите следующую команду:To see strings that are between 150 and 200 bytes, type the following:

    !dumpheap -type System.String -min 150 -max 200!dumpheap -type System.String -min 150 -max 200

    Далее приведен пример результатов команды.An example of the results is as follows.

    Address  MT           Size  Gen
    1875d2c0 790fa3e0      152    2 System.String HighlightNullStyle_Blotter_PendingOrder-11_Blotter_PendingOrder-11
    …
    

    Использование целого числа вместо строки для идентификаторов может быть более эффективным.Using an integer instead of a string for an ID can be more efficient. Если та же строка повторяется тысячи раз, рекомендуется настроить интернирование строк.If the same string is being repeated thousands of times, consider string interning. Дополнительные сведения об интернировании строк см. в разделе справки по методу String.Intern.For more information about string interning, see the reference topic for the String.Intern method.

Чтобы определить ссылки на объекты, выполните следующие действия.To determine references to objects

  • В WinDbg с загруженным расширением отладчика SOS введите следующую команду, чтобы получить список ссылок на объекты:In WinDbg with the SOS debugger extension loaded, type the following command to list references to objects:

    !gcroot!gcroot

    -or-

  • Чтобы определить ссылки для конкретного объекта, включите соответствующий адрес:To determine the references for a specific object, include the address:

    !gcroot 1c37b2ac!gcroot 1c37b2ac

    Корни, найденные в стеках, могут быть ложными положительными результатами.Roots found on stacks may be false positives. Чтобы получить дополнительные сведения, используйте команду !help gcroot.For more information, use the command !help gcroot.

    ebx:Root:19011c5c(System.Windows.Forms.Application+ThreadContext)->
    19010b78(DemoApp.FormDemoApp)->
    19011158(System.Windows.Forms.PropertyStore)->
    … [omitted]
    1c3745ec(System.Data.DataTable)->
    1c3747a8(System.Data.DataColumnCollection)->
    1c3747f8(System.Collections.Hashtable)->
    1c376590(System.Collections.Hashtable+bucket[])->
    1c376c98(System.Data.DataColumn)->
    1c37b270(System.Data.Common.DoubleStorage)->
    1c37b2ac(System.Double[])
    Scan Thread 0 OSTHread 99c
    Scan Thread 6 OSTHread 484
    

    Выполнение команды gcroot может занять много времени.The gcroot command can take a long time to finish. Любой объект, не освобождаемый сборщиком мусора, является активным объектом.Any object that is not reclaimed by garbage collection is a live object. Это означает, что некоторый корневой объект прямо или опосредованно привязан к данному объекту, поэтому команда gcroot должна возвращать сведения о пути к объекту.This means that some root is directly or indirectly holding onto the object, so gcroot should return path information to the object. Необходимо изучить возвращенные диаграммы, чтобы понять, на какие объекты по-прежнему имеются ссылки.You should examine the graphs returned and see why these objects are still referenced.

Чтобы определить, выполнялся ли метод завершения, выполните следующие действия.To determine whether a finalizer has been run

  • Запустите тестовую программу, содержащую следующий код:Run a test program that contains the following code:

    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();
    

    Если с помощью теста удалось разрешить проблему, значит сборщик мусора не освобождает объекты, так как методы завершения для этих объектов приостановлены.If the test resolves the problem, this means that the garbage collector was not reclaiming objects, because the finalizers for those objects had been suspended. Метод GC.WaitForPendingFinalizers позволяет методам завершения выполнить свои задачи и устраняет проблему.The GC.WaitForPendingFinalizers method enables the finalizers to complete their tasks, and fixes the problem.

Чтобы определить наличие объектов, ожидающих завершения, выполните следующие действия.To determine whether there are objects waiting to be finalized

  1. В отладчике Visual Studio или WinDbg с загруженным расширением отладчика SOS введите следующую команду:In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the following command:

    !finalizequeue!finalizequeue

    Проверьте число объектов, которые готовы к завершению.Look at the number of objects that are ready for finalization. Если число большое, необходимо выяснить, почему эти методы завершения вообще не могут выполняться или не могут выполняться достаточно быстро.If the number is high, you must examine why these finalizers cannot progress at all or cannot progress fast enough.

  2. Для получения выходных данных потоков, введите следующую команду:To get an output of threads, type the following command:

    threads -specialthreads -special

    Эта команда предоставляет примерно следующие выходные данные.This command provides output such as the following.

       OSID     Special thread type
    2    cd0    DbgHelper
    3    c18    Finalizer
    4    df0    GC SuspendEE
    

    Поток метода завершения указывает, какой метод завершения (при наличии) выполняется в настоящее время.The finalizer thread indicates which finalizer, if any, is currently being run. Если в потоке метода завершения не выполняются никакие методы завершения, значит он ожидает событие, которое запустит его выполнение.When a finalizer thread is not running any finalizers, it is waiting for an event to tell it to do its work. Как правило, поток находится в этом состоянии, так как выполняется с приоритетом THREAD_HIGHEST_PRIORITY и должен закончить выполнение методов завершения (при наличии) очень быстро.Most of the time you will see the finalizer thread in this state because it runs at THREAD_HIGHEST_PRIORITY and is supposed to finish running finalizers, if any, very quickly.

Чтобы определить объем свободного пространства в управляемой куче, выполните следующие действия.To determine the amount of free space in the managed heap

  • В отладчике Visual Studio или WinDbg с загруженным расширением отладчика SOS введите следующую команду:In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the following command:

    !dumpheap -type Free -stat!dumpheap -type Free -stat

    Эта команда выводит на экран общий размер всех свободных объектов в управляемой куче, как показано в следующем примере.This command displays the total size of all the free objects on the managed heap, as shown in the following example.

    total 230 objects
    Statistics:
          MT    Count    TotalSize Class Name
    00152b18      230     40958584      Free
    Total 230 objects
    
  • Чтобы определить объем свободного места в поколении 0, введите следующую команду, которая выводит сведения о потреблении памяти для каждого поколения:To determine the free space in generation 0, type the following command for memory consumption information by generation:

    !eeheap -gc!eeheap -gc

    Эта команда выводит примерно следующие сведения.This command displays output similar to the following. В последней строке показан эфемерный сегмент.The last line shows the ephemeral segment.

    Heap 0 (0015ad08)
    generation 0 starts at 0x49521f8c
    generation 1 starts at 0x494d7f64
    generation 2 starts at 0x007f0038
    ephemeral segment allocation context: none
    segment  begin     allocated  size
    00178250 7a80d84c  7a82f1cc   0x00021980(137600)
    00161918 78c50e40  78c7056c   0x0001f72c(128812)
    007f0000 007f0038  047eed28   0x03ffecf0(67103984)
    3a120000 3a120038  3a3e84f8   0x002c84c0(2917568)
    46120000 46120038  49e05d04   0x03ce5ccc(63855820)
    
  • Вычислите пространство, используемое поколением 0:Calculate the space used by generation 0:

    ? 49e05d04-0x49521f8c? 49e05d04-0x49521f8c

    Далее приведен результат.The result is as follows. Поколение 0 занимает приблизительно 9 МБ.Generation 0 is approximately 9 MB.

    Evaluate expression: 9321848 = 008e3d78
    
  • Следующая команда создает дамп свободного места в диапазоне поколения 0:The following command dumps the free space within the generation 0 range:

    !dumpheap -type Free -stat 0x49521f8c 49e05d04!dumpheap -type Free -stat 0x49521f8c 49e05d04

    Далее приведен результат.The result is as follows.

    ------------------------------
    Heap 0
    total 409 objects
    ------------------------------
    Heap 1
    total 0 objects
    ------------------------------
    Heap 2
    total 0 objects
    ------------------------------
    Heap 3
    total 0 objects
    ------------------------------
    total 409 objects
    Statistics:
          MT    Count TotalSize Class Name
    0015a498      409   7296540      Free
    Total 409 objects
    

    Эти выходные данные показывают, что часть кучи поколения 0 использует 9 МБ пространства для объектов, а 7 МБ свободны.This output shows that the generation 0 portion of the heap is using 9 MB of space for objects and has 7 MB free. Этот анализ показывает предел, до которого поколение 0 участвует в фрагментации.This analysis shows the extent to which generation 0 contributes to fragmentation. Этот объем используемой памяти кучи необходимо вычесть из общего объема как причину фрагментации долгосрочными объектами.This amount of heap usage should be discounted from the total amount as the cause of fragmentation by long-term objects.

Чтобы определить количество закрепленных объектов, выполните следующие действия.To determine the number of pinned objects

  • В отладчике Visual Studio или WinDbg с загруженным расширением отладчика SOS введите следующую команду:In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the following command:

    !gchandles!gchandles

    Выводимая на экран статистика включает число закрепленных дескрипторов, как показано в следующем примере.The statistics displayed includes the number of pinned handles, as the following example shows.

    GC Handle Statistics:
    Strong Handles:      29
    Pinned Handles:      10
    

Чтобы определить продолжительность сборки мусора, выполните следующие действия.To determine the length of time in a garbage collection

  • Проверьте счетчик производительности памяти % Time in GC.Examine the % Time in GC memory performance counter.

    Значение вычисляется с помощью интервала выборки.The value is calculated by using a sample interval time. Поскольку счетчики обновляются в конце каждой сборки мусора, текущая выборка будет иметь то же значение, что и предыдущая, если в течение интервала не будут выполняться сборки мусора.Because the counters are updated at the end of each garbage collection, the current sample will have the same value as the previous sample if no collections occurred during the interval.

    Время сборки вычисляется путем умножения интервала выборки на процентное значение.Collection time is obtained by multiplying the sample interval time with the percentage value.

    В следующих данных показаны четыре интервала выборки продолжительностью две секунды для 8-секундного исследования.The following data shows four sampling intervals of two seconds, for an 8-second study. Столбцы Gen0, Gen1 и Gen2 показывают количество сборок мусора, выполнявшихся в течение этого интервала для данного поколения.The Gen0, Gen1, and Gen2 columns show the number of garbage collections that occurred during that interval for that generation.

    Interval    Gen0    Gen1    Gen2    % Time in GC
            1       9       3       1              10
            2      10       3       1               1
            3      11       3       1               3
            4      11       3       1               3
    

    Эти сведения не указывают на момент выполнения сборки мусора, но вы можете определить число сборок, выполнявшихся в определенный интервал.This information does not show when the garbage collection occurred, but you can determine the number of garbage collections that occurred in an interval of time. В худшем случае десятая сборка мусора поколения 0 завершается в начале второго интервала, а одиннадцатая сборка мусора поколения 0 завершается в конце пятого интервала.Assuming the worst case, the tenth generation 0 garbage collection finished at the start of the second interval, and the eleventh generation 0 garbage collection finished at the end of the fifth interval. Время между окончанием десятой и одиннадцатой сборок мусора составляет 2 секунды, а счетчик производительности выдает значение 3 %, таким образом длительность одиннадцатой сборки мусора поколения 0 составляет (2 секунды * 3 % =) 60 мс.The time between the end of the tenth and the end of the eleventh garbage collection is about 2 seconds, and the performance counter shows 3%, so the duration of the eleventh generation 0 garbage collection was (2 seconds * 3% = 60ms).

    В этом примере приведено 5 периодов.In this example, there are 5 periods.

    Interval    Gen0    Gen1    Gen2     % Time in GC
            1       9       3       1                3
            2      10       3       1                1
            3      11       4       2                1
            4      11       4       2                1
            5      11       4       2               20
    

    Вторая сборка поколения 2 запускается во время третьего интервала и завершается в пятом интервале.The second generation 2 garbage collection started during the third interval and finished at the fifth interval. В худшем случае последняя сборка мусора поколения 0 завершается в начале второго интервала, а сборка мусора поколения 2 завершается в конце пятого интервала.Assuming the worst case, the last garbage collection was for a generation 0 collection that finished at the start of the second interval, and the generation 2 garbage collection finished at the end of the fifth interval. Таким образом, время между завершением сборки мусора для поколения 0 и завершением сборки мусора для поколения 2 составляет 4 секунды.Therefore, the time between the end of the generation 0 garbage collection and the end of the generation 2 garbage collection is 4 seconds. Поскольку счетчик % Time in GC выдает значение 20 %, максимальная длительность сборки мусора поколения 2 могла составлять (4 секунды * 20 % =) 800 мс.Because the % Time in GC counter is 20%, the maximum amount of time the generation 2 garbage collection could have taken is (4 seconds * 20% = 800ms).

  • Кроме того, продолжительность сборки мусора можно определить с помощью событий ETW для сборки мусора, проанализировав данные для выяснения длительности сборки мусора.Alternatively, you can determine the length of a garbage collection by using garbage collection ETW events, and analyze the information to determine the duration of garbage collection.

    Например, следующие данные показывают последовательность событий, возникших во время непараллельной сборки мусора.For example, the following data shows an event sequence that occurred during a non-concurrent garbage collection.

    Timestamp    Event name
    513052        GCSuspendEEBegin_V1
    513078        GCSuspendEEEnd
    513090        GCStart_V1
    517890        GCEnd_V1
    517894        GCHeapStats
    517897        GCRestartEEBegin
    517918        GCRestartEEEnd
    

    Приостановка управляемого потока заняла 26 мкс (GCSuspendEEEndGCSuspendEEBegin_V1).Suspending the managed thread took 26us (GCSuspendEEEndGCSuspendEEBegin_V1).

    Фактическая сборка мусора заняла 4,8 мс (GCEnd_V1GCStart_V1).The actual garbage collection took 4.8ms (GCEnd_V1GCStart_V1).

    Возобновление управляемого потока заняло 21 мкс (GCRestartEEEndGCRestartEEBegin).Resuming the managed threads took 21us (GCRestartEEEndGCRestartEEBegin).

    Следующие выходные данные содержат пример фоновой сборки мусора и включают сведения о процессе, потоке и полях событийThe following output provides an example for background garbage collection, and includes the process, thread, and event fields. (показаны не все данные).(Not all data is shown.)

    timestamp(us)    event name            process    thread    event field
    42504385        GCSuspendEEBegin_V1    Test.exe    4372             1
    42504648        GCSuspendEEEnd         Test.exe    4372
    42504816        GCStart_V1             Test.exe    4372        102019
    42504907        GCStart_V1             Test.exe    4372        102020
    42514170        GCEnd_V1               Test.exe    4372
    42514204        GCHeapStats            Test.exe    4372        102020
    42832052        GCRestartEEBegin       Test.exe    4372
    42832136        GCRestartEEEnd         Test.exe    4372
    63685394        GCSuspendEEBegin_V1    Test.exe    4744             6
    63686347        GCSuspendEEEnd         Test.exe    4744
    63784294        GCRestartEEBegin       Test.exe    4744
    63784407        GCRestartEEEnd         Test.exe    4744
    89931423        GCEnd_V1               Test.exe    4372        102019
    89931464        GCHeapStats            Test.exe    4372
    

    Событие GCStart_V1 на отметке 42504816 указывает на выполнение фоновой сборки мусора, так как последнее поле — 1.The GCStart_V1 event at 42504816 indicates that this is a background garbage collection, because the last field is 1. Оно становится сборкой мусораThis becomes garbage collection No. 102019.102019.

    Событие GCStart возникает из-за необходимости выполнить эфемерную сборку мусора до запуска фоновой сборки мусора.The GCStart event occurs because there is a need for an ephemeral garbage collection before you start a background garbage collection. Оно становится сборкой мусораThis becomes garbage collection No. 102020.102020.

    На отметке 42514170 завершается выполнение сборки мусораAt 42514170, garbage collection No. 102020.102020 finishes. На этом этапе перезапускаются управляемые потоки.The managed threads are restarted at this point. Это действие выполняется для потока 4372, активировавшего эту фоновую сборку мусора.This is completed on thread 4372, which triggered this background garbage collection.

    Для потока 4744 происходит приостановка.On thread 4744, a suspension occurs. Это единственный случай, когда фоновой сборке мусора приходится приостанавливать управляемые потоки.This is the only time at which the background garbage collection has to suspend managed threads. Продолжительность приостановки составляет примерно 99 мс ((63784407-63685394)/1000).This duration is approximately 99ms ((63784407-63685394)/1000).

    Событие GCEnd для фоновой сборки мусора находится на отметке 89931423.The GCEnd event for the background garbage collection is at 89931423. Это означает, что фоновая сборка мусора продолжалась около 47 секунд ((89931423-42504816)/1000).This means that the background garbage collection lasted for about 47seconds ((89931423-42504816)/1000).

    Во время выполнения управляемых потоков можно наблюдать любое количество эфемерных сборок мусора.While the managed threads are running, you can see any number of ephemeral garbage collections occurring.

Чтобы определить, что активировало сборку мусора, выполните следующие действия.To determine what triggered a garbage collection

  • В отладчике Visual Studio или WinDbg с загруженным расширением отладчика SOS введите следующую команду, чтобы вывести на экран все потоки со стеками вызовов:In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the following command to show all the threads with their call stacks:

    ~*kb~*kb

    Эта команда выводит примерно следующие сведения.This command displays output similar to the following.

    0012f3b0 79ff0bf8 mscorwks!WKS::GCHeap::GarbageCollect
    0012f454 30002894 mscorwks!GCInterface::CollectGeneration+0xa4
    0012f490 79fa22bd fragment_ni!request.Main(System.String[])+0x48
    

    Если сборка мусора была вызвана уведомлением о нехватке памяти от операционной системы, стек вызовов аналогичен за исключением того, что поток является потоком метода завершения.If the garbage collection was caused by a low memory notification from the operating system, the call stack is similar, except that the thread is the finalizer thread. Поток метода завершения получает асинхронное уведомление о нехватке памяти и запускает сборку мусора.The finalizer thread gets an asynchronous low memory notification and induces the garbage collection.

    Если сборка мусора вызвана выделением памяти, стек будет следующим:If the garbage collection was caused by memory allocation, the stack appears as follows:

    0012f230 7a07c551 mscorwks!WKS::GCHeap::GarbageCollectGeneration
    0012f2b8 7a07cba8 mscorwks!WKS::gc_heap::try_allocate_more_space+0x1a1
    0012f2d4 7a07cefb mscorwks!WKS::gc_heap::allocate_more_space+0x18
    0012f2f4 7a02a51b mscorwks!WKS::GCHeap::Alloc+0x4b
    0012f310 7a02ae4c mscorwks!Alloc+0x60
    0012f364 7a030e46 mscorwks!FastAllocatePrimitiveArray+0xbd
    0012f424 300027f4 mscorwks!JIT_NewArr1+0x148
    000af70f 3000299f fragment_ni!request..ctor(Int32, Single)+0x20c
    0000002a 79fa22bd fragment_ni!request.Main(System.String[])+0x153
    

    Вспомогательный JIT-объект (JIT_New*) в конечном итоге вызывает GCHeap::GarbageCollectGeneration.A just-in-time helper (JIT_New*) eventually calls GCHeap::GarbageCollectGeneration. Если выяснилось, что сборки мусора поколения 2 вызываются выделением памяти, необходимо определить, какие объекты собираются при сборке мусора поколения 2, и постараться избежать их.If you determine that generation 2 garbage collections are caused by allocations, you must determine which objects are collected by a generation 2 garbage collection and how to avoid them. То есть необходимо определить разницу между началом и концом сборки мусора поколения 2 и выяснить, какие объекты, вызвали сборку мусора поколения 2.That is, you want to determine the difference between the start and the end of a generation 2 garbage collection, and the objects that caused the generation 2 collection.

    Например, введите в отладчике следующую команду, чтобы вывести на экран время начала сборки поколения 2:For example, type the following command in the debugger to show the beginning of a generation 2 collection:

    !dumpheap –stat!dumpheap –stat

    Пример выходных данных (сокращено для отображения объектов, использующих наибольшее пространство):Example output (abridged to show the objects that use the most space):

    79124228    31857      9862328 System.Object[]
    035f0384    25668     11601936 Toolkit.TlkPosition
    00155f80    21248     12256296      Free
    79103b6c   297003     13068132 System.Threading.ReaderWriterLock
    7a747ad4   708732     14174640 System.Collections.Specialized.HybridDictionary
    7a747c78   786498     15729960 System.Collections.Specialized.ListDictionary+DictionaryNode
    7a747bac   700298     19608344 System.Collections.Specialized.ListDictionary
    035f0ee4    89192     38887712 Toolkit.TlkOrder
    00fcae40     6193     44911636 WaveBasedStrategy.Tick_Snap[]
    7912c444    91616     71887080 System.Double[]
    791242ec    32451     82462728 System.Collections.Hashtable+bucket[]
    790fa3e0  2459154    112128436 System.String
    Total 6471774 objects
    

    Повторите команду в конце сборки поколения 2:Repeat the command at the end of generation 2:

    !dumpheap –stat!dumpheap –stat

    Пример выходных данных (сокращено для отображения объектов, использующих наибольшее пространство):Example output (abridged to show the objects that use the most space):

    79124228    26648      9314256 System.Object[]
    035f0384    25668     11601936 Toolkit.TlkPosition
    79103b6c   296770     13057880 System.Threading.ReaderWriterLock
    7a747ad4   708730     14174600 System.Collections.Specialized.HybridDictionary
    7a747c78   786497     15729940 System.Collections.Specialized.ListDictionary+DictionaryNode
    7a747bac   700298     19608344 System.Collections.Specialized.ListDictionary
    00155f80    13806     34007212      Free
    035f0ee4    89187     38885532 Toolkit.TlkOrder
    00fcae40     6193     44911636 WaveBasedStrategy.Tick_Snap[]
    791242ec    32370     82359768 System.Collections.Hashtable+bucket[]
    790fa3e0  2440020    111341808 System.String
    Total 6417525 objects
    

    Объекты double[] больше не отображаются в конце списка выходных данных, что означает, что они были собраны.The double[] objects disappeared from the end of the output, which means that they were collected. На эти объекты приходится приблизительно 70 МБ.These objects account for approximately 70 MB. Остальные объекты не сильно изменились.The remaining objects did not change much. Следовательно, эти объекты double[] были причиной выполнения этой сборки мусора поколения 2.Therefore, these double[] objects were the reason why this generation 2 garbage collection occurred. Затем вам потребуется выяснить, почему объекты double[] попали в сборку и почему они перестали использоваться.Your next step is to determine why the double[] objects are there and why they died. Происхождение этих объектов можно узнать от разработчика или с помощью команды gcroot.You can ask the code developer where these objects came from, or you can use the gcroot command.

Чтобы определить, вызвана ли высокая загрузка ЦП сборкой мусора, выполните следующие действия.To determine whether high CPU usage is caused by garbage collection

  • Сопоставьте значение счетчика производительности памяти % Time in GC с временем обработки.Correlate the % Time in GC memory performance counter value with the process time.

    Если значение % Time in GC резко возрастает одновременно с временем обработки, значит сборка мусора вызывает высокую загрузку ЦП.If the % Time in GC value spikes at the same time as process time, garbage collection is causing a high CPU usage. В противном случае выполните профилирование приложения, чтобы определить, где возникает высокая загрузка.Otherwise, profile the application to find where the high usage is occurring.

См. такжеSee also