Recolección de elementos no utilizados y rendimientoGarbage Collection and Performance

En este tema se describen problemas relacionados con la recolección de elementos no utilizados y el uso de memoria.This topic describes issues related to garbage collection and memory usage. Se tratan problemas relativos al montón administrado y se explica cómo minimizar el efecto de la recolección de elementos no utilizados en las aplicaciones.It addresses issues that pertain to the managed heap and explains how to minimize the effect of garbage collection on your applications. Cada problema contiene vínculos a procedimientos que puede emplear para investigar los problemas.Each issue has links to procedures that you can use to investigate problems.

Este tema contiene las siguientes secciones:This topic contains the following sections:

Herramientas de análisis de rendimientoPerformance Analysis Tools

En las próximas siguientes se describen las herramientas disponibles para investigar los problemas de uso de memoria y de recolección de elementos no utilizados.The following sections describe the tools that are available for investigating memory usage and garbage collection issues. Los procedimientos que se muestran más adelante en este tema hacen referencia a estas herramientas.The procedures provided later in this topic refer to these tools.

Contadores de rendimiento de memoriaMemory Performance Counters

Puede usar contadores de rendimiento para recopilar datos de rendimiento.You can use performance counters to gather performance data. Para obtener instrucciones, vea Runtime Profiling (Generación de perfiles en tiempo de ejecución).For instructions, see Runtime Profiling. La categoría CLR Memory de contadores de rendimiento de .NET, tal y como se describe en Performance Counters in the .NET Framework (Contadores de rendimiento de .NET Framework), ofrece información sobre el recolector de elementos no utilizados.The .NET CLR Memory category of performance counters, as described in Performance Counters in the .NET Framework, provides information about the garbage collector.

Depurar con SOSDebugging with SOS

Puede usar el depurador de Windows (WinDbg) para inspeccionar objetos del montón administrado.You can use the Windows Debugger (WinDbg) to inspect objects on the managed heap.

Para instalar WinDbg, instale las Herramientas de depuración para Windows desde la página Download Debugging Tools for Windows (Descarga de Herramientas de depuración para Windows).To install WinDbg, install Debugging Tools for Windows from the Download Debugging Tools for Windows page.

Eventos ETW de recolección de elementos no utilizadosGarbage Collection ETW Events

El seguimiento de eventos para Windows (ETW) es un sistema de traza que complementa la compatibilidad con generación de perfiles y depuración proporcionada por .NET Framework.Event tracing for Windows (ETW) is a tracing system that supplements the profiling and debugging support provided by the .NET Framework. A partir de .NET Framework 4, los eventos ETW de recolección de elementos no utilizados capturan información útil para analizar el montón administrado desde un punto de vista estadístico.Starting with the .NET Framework 4, garbage collection ETW events capture useful information for analyzing the managed heap from a statistical point of view. Por ejemplo, el evento GCStart_V1, que se genera cuando está a punto de producirse una recolección de elementos no utilizados, proporciona la siguiente información:For example, the GCStart_V1 event, which is raised when a garbage collection is about to occur, provides the following information:

  • La generación de objetos que se recolecta.Which generation of objects is being collected.

  • Lo que desencadenó la recolección de elementos no utilizados.What triggered the garbage collection.

  • Tipo de recolección de elementos no utilizados (simultánea o no simultánea).Type of garbage collection (concurrent or not concurrent).

El registro de eventos ETW es eficaz y no enmascara ningún problema de rendimiento asociado a la recolección de elementos no utilizados.ETW event logging is efficient and will not mask any performance problems associated with garbage collection. Un proceso puede proporcionar sus propios eventos junto con los eventos ETW.A process can provide its own events in conjunction with ETW events. Cuando se registran, tanto los eventos de la aplicación como los eventos de la recolección de elementos no utilizados se pueden poner en correlación para determinar cómo y cuándo se producen problemas de pila.When logged, both the application's events and the garbage collection events can be correlated to determine how and when heap problems occur. Por ejemplo, una aplicación de servidor puede proporcionar eventos al comienzo y al final de una solicitud de cliente.For example, a server application could provide events at the start and end of a client request.

La API de generación de perfilesThe Profiling API

Las interfaces de generación de perfiles de Common Language Runtime (CLR) proporcionan información detallada sobre los objetos que se vieron afectados durante la recolección de elementos no utilizados.The common language runtime (CLR) profiling interfaces provide detailed information about the objects that were affected during garbage collection. Un generador de perfiles puede recibir una notificación cuando se inicia y finaliza una recolección de elementos no utilizados.A profiler can be notified when a garbage collection starts and ends. Puede proporcionar informes sobre los objetos del montón administrado, incluida una identificación de los objetos de cada generación.It can provide reports about the objects on the managed heap, including an identification of objects in each generation. Para más información, consulte Profiling Overview (Información general sobre generación de perfiles).For more information, see Profiling Overview.

Los generadores de perfiles pueden proporcionar información completa.Profilers can provide comprehensive information. Sin embargo, los generadores de perfiles complejos pueden modificar el comportamiento de una aplicación.However, complex profilers can potentially modify an application's behavior.

Supervisión de recursos de dominio de aplicaciónApplication Domain Resource Monitoring

A partir de .NET Framework 4, la supervisión de recursos de dominio de aplicación (ARM) permite a los anfitriones supervisar el uso de la CPU y la memoria por parte del dominio de aplicación.Starting with the .NET Framework 4, Application domain resource monitoring (ARM) enables hosts to monitor CPU and memory usage by application domain. Para más información, consulte Application Domain Resource Monitoring (Supervisión de recursos de dominio de aplicación).For more information, see Application Domain Resource Monitoring.

Volver al principioBack to top

Solucionar problemas de rendimientoTroubleshooting Performance Issues

El primer paso consiste en determinar si el problema es realmente la recolección de elementos no utilizados.The first step is to determine whether the issue is actually garbage collection. Si determina que lo es, seleccione un elemento de la lista siguiente para solucionar el problema.If you determine that it is, select from the following list to troubleshoot the problem.

Problema: Se inicia una excepción de memoria insuficienteIssue: An Out-of-Memory Exception Is Thrown

Hay dos casos justificados para que se produzca una excepción OutOfMemoryException administrada:There are two legitimate cases for a managed OutOfMemoryException to be thrown:

  • La escasez de memoria virtual.Running out of virtual memory.

    El recolector de elementos no utilizados asigna memoria del sistema en segmentos de un tamaño predeterminado.The garbage collector allocates memory from the system in segments of a pre-determined size. Si una asignación necesita un segmento adicional, pero no queda ningún bloque libre contiguo en el espacio de memoria virtual del proceso, se producirá un error en la asignación del montón administrado.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.

  • No tener suficiente memoria física para asignar.Not having enough physical memory to allocate.

Comprobaciones de rendimientoPerformance checks
Determine si la excepción de memoria insuficiente está administrada.Determine whether the out-of-memory exception is managed.

Determine cuánta memoria virtual se puede reservar.Determine how much virtual memory can be reserved.

Determine si hay suficiente memoria física.Determine whether there is enough physical memory.

Si determina que la excepción no es legítima, póngase en contacto con el servicio de atención al cliente y soporte técnico de Microsoft, y proporcione la información siguiente:If you determine that the exception is not legitimate, contact Microsoft Customer Service and Support with the following information:

  • La pila con la excepción administrada de memoria insuficiente.The stack with the managed out-of-memory exception.

  • Un volcado de memoria completo.Full memory dump.

  • Los datos que demuestran que no es una excepción legítima de memoria insuficiente, incluidos los datos que muestran que la memoria virtual o la memoria física no supone ningún problema.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.

Problema: El proceso usa demasiada memoriaIssue: The Process Uses Too Much Memory

Un supuesto común es que el uso de memoria que aparece en la pestaña Rendimiento del Administrador de tareas de Windows puede indicar cuándo se está usando demasiada memoria.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. Sin embargo, esa información pertenece al espacio de trabajo; no proporciona información sobre el uso de memoria virtual.However, that display pertains to the working set; it does not provide information about virtual memory usage.

Si determina que el problema está provocado por el montón administrado, debe medir el montón administrado a lo largo del tiempo para determinar cualquier patrón.If you determine that the issue is caused by the managed heap, you must measure the managed heap over time to determine any patterns.

Si determina que el problema no está provocado por el montón administrado, debe usar la depuración nativa.If you determine that the problem is not caused by the managed heap, you must use native debugging.

Comprobaciones de rendimientoPerformance checks
Determine cuánta memoria virtual se puede reservar.Determine how much virtual memory can be reserved.

Determine cuánta memoria está confirmando el montón administrado.Determine how much memory the managed heap is committing.

Determine cuánta memoria reserva el montón administrado.Determine how much memory the managed heap reserves.

Determine los objetos grandes de la generación 2.Determine large objects in generation 2.

Determine las referencias a objetos.Determine references to objects.

Problema: El recolector de elementos no utilizados no recupera los objetos con la rapidez suficienteIssue: The Garbage Collector Does Not Reclaim Objects Fast Enough

Cuando parezca que la recolección de elementos no utilizados no está recuperando los objetos según lo esperado, debe determinar si hay alguna referencia segura a esos objetos.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.

También puede encontrar este problema si no se ha producido ninguna recolección de elementos no utilizados para la generación que contiene un objeto muerto, lo que indica que el finalizador del objeto muerto no se ha ejecutado.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. Por ejemplo, esto puede ocurrir cuando se ejecuta una aplicación de contenedor uniproceso (STA) y el subproceso que atiende a la cola del finalizador no la puede llamar.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.

Comprobaciones de rendimientoPerformance checks
Compruebe las referencias a objetos.Check references to objects.

Determine si se ha ejecutado un finalizador.Determine whether a finalizer has been run.

Determine si hay objetos en espera de finalización.Determine whether there are objects waiting to be finalized.

Problema: El montón administrado está demasiado fragmentadoIssue: The Managed Heap Is Too fragmented

El nivel de fragmentación se calcula como la proporción de espacio disponible con respecto a la memoria total asignada para la generación.The fragmentation level is calculated as the ratio of free space over the total allocated memory for the generation. Para la generación 2, un nivel aceptable de fragmentación es inferior al 20%.For generation 2, an acceptable level of fragmentation is no more than 20%. Puesto que la generación 2 puede llegar a ser muy grande, la proporción de fragmentación es más importante que el valor absoluto.Because generation 2 can get very big, the ratio of fragmentation is more important than the absolute value.

El hecho de tener mucho espacio disponible en la generación 0 no supone ningún problema porque esta es la generación donde se asignan nuevos objetos.Having lots of free space in generation 0 is not a problem because this is the generation where new objects are allocated.

Siempre se produce fragmentación en el montón de objetos grandes porque no se compacta.Fragmentation always occurs in the large object heap because it is not compacted. Los objetos libres adyacentes se contraen de forma natural en un único espacio para satisfacer las solicitudes de asignación de objetos grandes.Free objects that are adjacent are naturally collapsed into a single space to satisfy large object allocation requests.

La fragmentación puede convertirse en un problema en las generaciones 1 y 2.Fragmentation can become a problem in generation 1 and generation 2. Si estas generaciones tienen una gran cantidad de espacio disponible después de una recolección de elementos no utilizados, el uso de objetos de una aplicación puede necesitar modificaciones y debe considerar la posibilidad de volver a evaluar la duración de los objetos de larga duración.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.

El anclaje excesivo de objetos puede aumentar la fragmentación.Excessive pinning of objects can increase fragmentation. Si la fragmentación es elevada, puede que haya demasiados objetos anclados.If fragmentation is high, too many objects could be pinned.

Si la fragmentación de la memoria virtual está impidiendo que el recolector de elementos no utilizados agregue segmentos, puede deberse a una de las causas siguientes:If fragmentation of virtual memory is preventing the garbage collector from adding segments, the causes could be one of the following:

  • Carga y descarga frecuentes de muchos ensamblados pequeños.Frequent loading and unloading of many small assemblies.

  • Almacenamiento de demasiadas referencias a objetos COM al interoperar con código no administrado.Holding too many references to COM objects when interoperating with unmanaged code.

  • Creación de objetos grandes transitorios, lo que hace que el montón de objetos grandes asigne y libere segmentos del montón con frecuencia.Creation of large transient objects, which causes the large object heap to allocate and free heap segments frequently.

    Al hospedar el CLR, una aplicación puede solicitar que el recolector de elementos no utilizados conserve sus segmentos.When hosting the CLR, an application can request that the garbage collector retain its segments. Esto reduce la frecuencia de las asignaciones de segmentos.This reduces the frequency of segment allocations. Para ello se emplea la marca STARTUP_HOARD_GC_VM en la enumeración STARTUP_FLAGS.This is accomplished by using the STARTUP_HOARD_GC_VM flag in the STARTUP_FLAGS Enumeration.

Comprobaciones de rendimientoPerformance checks
Determine la cantidad de espacio disponible en el montón administrado.Determine the amount of free space in the managed heap.

Determine el número de objetos anclados.Determine the number of pinned objects.

Si cree que no hay ninguna causa que justifique la fragmentación, póngase en contacto con el servicio de atención al cliente y soporte técnico de Microsoft.If you think that there is no legitimate cause for the fragmentation, contact Microsoft Customer Service and Support.

Problema: Las pausas de la recolección de elementos no utilizados son demasiado largasIssue: Garbage Collection Pauses Are Too Long

La recolección de elementos no utilizados funciona en tiempo real flexible, por lo que una aplicación debe poder tolerar algunas pausas.Garbage collection operates in soft real time, so an application must be able to tolerate some pauses. Un criterio para el tiempo real flexible es que el 95% de las operaciones debe finalizar a tiempo.A criterion for soft real time is that 95% of the operations must finish on time.

En la recolección de elementos no utilizados simultánea, se permite la ejecución de subprocesos administrados durante una recolección, lo que significa que las pausas son mínimas.In concurrent garbage collection, managed threads are allowed to run during a collection, which means that pauses are very minimal.

Las recolecciones de elementos no utilizados efímeras (las generaciones 0 y 1) solo duran algunos milisegundos, por lo que no suele ser viable reducir las pausas.Ephemeral garbage collections (generations 0 and 1) last only a few milliseconds, so decreasing pauses is usually not feasible. Sin embargo, puede reducir las pausas en las recolecciones de la generación 2 cambiando el modelo de las solicitudes de asignación de una aplicación.However, you can decrease the pauses in generation 2 collections by changing the pattern of allocation requests by an application.

Otro método más preciso consiste en usar eventos ETW de recolección de elementos no utilizados.Another, more accurate, method is to use garbage collection ETW events. Puede averiguar los controles de tiempo para las recolecciones si suma las diferencias de marca de tiempo para una secuencia de eventos.You can find the timings for collections by adding the time stamp differences for a sequence of events. La secuencia de recolección completa incluye la suspensión del motor de ejecución, la recolección de elementos no utilizados propiamente dicha y la reanudación del motor de ejecución.The whole collection sequence includes suspension of the execution engine, the garbage collection itself, and the resumption of the execution engine.

Puede usar notificaciones de recolección de elementos no utilizados para determinar si se va a realizar una recolección de generación 2 en un servidor y si redirigir las solicitudes a otro servidor podría solucionar los problemas de las pausas.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.

Comprobaciones de rendimientoPerformance checks
Determine la duración de una recolección de elementos no utilizados.Determine the length of time in a garbage collection.

Determine lo que desencadenó una recolección de elementos no utilizados.Determine what caused a garbage collection.

Problema: La generación 0 es demasiado grandeIssue: Generation 0 Is Too Big

Es probable que la generación 0 tenga un número mayor de objetos en un sistema de 64 bits, sobre todo cuando se usa la recolección de elementos no utilizados de servidor en lugar de la de estación de trabajo.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. Esto se debe a que el umbral para desencadenar una recolección de elementos no utilizados de generación 0 es más alto en estos entornos y las recolecciones de generación 0 pueden llegar a ser mucho mayores.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. El rendimiento mejora cuando una aplicación asigna más memoria antes de que se desencadene una recolección de elementos no utilizados.Performance is improved when an application allocates more memory before a garbage collection is triggered.

Problema: El uso de CPU durante una recolección de elementos no utilizados es demasiado altoIssue: CPU Usage During a Garbage Collection Is Too High

El uso de CPU será elevado durante una recolección de elementos no utilizados.CPU usage will be high during a garbage collection. Si se dedica una cantidad significativa de tiempo de proceso a una recolección de elementos no utilizados, el número de recolecciones es demasiado frecuente o la recolección está durando demasiado.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. Una proporción de asignación de objetos mayor en el montón administrado hace que la recolección de elementos no utilizados se realice con más frecuencia.An increased allocation rate of objects on the managed heap causes garbage collection to occur more frequently. Al disminuir la proporción de asignación se reduce la frecuencia de las recolecciones de elementos no utilizados.Decreasing the allocation rate reduces the frequency of garbage collections.

Puede supervisar las proporciones de asignación mediante el contador de rendimiento Allocated Bytes/second.You can monitor allocation rates by using the Allocated Bytes/second performance counter. Para más información, consulte Performance Counters in the .NET Framework (Contadores de rendimiento de .NET Framework).For more information, see Performance Counters in the .NET Framework.

La duración de una recolección suele depender del número de objetos que sobrevivan después de la asignación.The duration of a collection is primarily a factor of the number of objects that survive after allocation. El recolector de elementos no utilizados debe pasar por una gran cantidad de memoria si hay que recolectar muchos objetos.The garbage collector must go through a large amount of memory if many objects remain to be collected. El trabajo para compactar los supervivientes lleva mucho tiempo.The work to compact the survivors is time-consuming. Para determinar cuántos objetos se controlaron durante una recolección, establezca un punto de interrupción en el depurador al final de una recolección de elementos no utilizados para una generación especificada.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.

Comprobaciones de rendimientoPerformance checks
Determine si el uso elevado de CPU está provocado por la recolección de elementos no utilizados.Determine if high CPU usage is caused by garbage collection.

Establezca un punto de interrupción al final de la recolección de elementos no utilizados.Set a breakpoint at the end of garbage collection.

Volver al principioBack to top

Instrucciones para la solución de problemasTroubleshooting Guidelines

En esta sección se describen instrucciones debe tener en cuenta cuando empiece las investigaciones.This section describes guidelines that you should consider as you begin your investigations.

Recolección de elementos no utilizados de estación de trabajo o de servidorWorkstation or Server Garbage Collection

Determine si está usando el tipo correcto de recolección de elementos no utilizados.Determine if you are using the correct type of garbage collection. Si la aplicación emplea varios subprocesos e instancias de objeto, use la recolección de elementos no utilizados de servidor en lugar de la de estación de trabajo.If your application uses multiple threads and object instances, use server garbage collection instead of workstation garbage collection. La recolección de elementos no utilizados de servidor funciona en varios subprocesos, mientras que la de estación de trabajo necesita que varias instancias de una aplicación ejecuten sus propios subprocesos de recolección de elementos no utilizados y compitan por el tiempo de CPU.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.

Una aplicación que tenga una carga baja y realice tareas con poca frecuencia en segundo plano, como un servicio, puede usar la recolección de elementos no utilizados de estación de trabajo con la recolección simultánea de elementos no utilizados deshabilitada.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.

Cuándo medir el tamaño del montón administradoWhen to Measure the Managed Heap Size

A menos que esté usando un generador de perfiles, tendrá que establecer un modelo de medida coherente para diagnosticar eficazmente los problemas de rendimiento.Unless you are using a profiler, you will have to establish a consistent measuring pattern to effectively diagnose performance issues. Tenga en cuenta lo siguiente a la hora de establecer una programación:Consider the following points to establish a schedule:

  • Si mide después de una recolección de elementos no utilizados de generación 2, todo el montón administrado estará libre de elementos no utilizados (objetos muertos).If you measure after a generation 2 garbage collection, the entire managed heap will be free of garbage (dead objects).

  • Si mide inmediatamente después de una recolección de elementos no utilizados de generación 0, los objetos de las generaciones 1 y 2 no se recolectarán todavía.If you measure immediately after a generation 0 garbage collection, the objects in generations 1 and 2 will not be collected yet.

  • Si mide inmediatamente antes de una recolección de elementos no utilizados, se medirá toda la asignación posible antes de que comience dicha recolección.If you measure immediately before a garbage collection, you will measure as much allocation as possible before the garbage collection starts.

  • La medición durante una recolección de elementos no utilizados es problemática, ya que las estructuras de datos del recolector de elementos no utilizados no están en un estado válido para el cruce seguro y quizás no se obtengan resultados completos.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. Esto es intencionado.This is by design.

  • Cuando se usa la recolección de elementos no utilizados de estación de trabajo con la recolección simultánea de elementos no utilizados, los objetos recuperados no se compactan, por lo que el tamaño del montón puede ser igual o mayor (la fragmentación puede hacer que parezca mayor).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).

  • La recolección de elementos no utilizados simultánea en la generación 2 se retrasa cuando la carga de memoria física es demasiado alta.Concurrent garbage collection on generation 2 is delayed when the physical memory load is too high.

En el procedimiento siguiente se describe cómo establecer un punto de interrupción para que pueda medir el montón administrado.The following procedure describes how to set a breakpoint so that you can measure the managed heap.

Para establecer un punto de interrupción al final de la recolección de elementos no utilizadosTo set a breakpoint at the end of garbage collection
  • En WinDbg con la extensión del depurador de SOS cargada, escriba el comando siguiente: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'"

    donde GcCondemnedGeneration se establece en la generación que se prefiera.where GcCondemnedGeneration is set to the desired generation. Este comando necesita símbolos privados.This command requires private symbols.

    Este comando fuerza una interrupción si RestartEE se ejecuta una vez recuperados los objetos de generación 2 para la recolección de elementos no utilizados.This command forces a break if RestartEE is executed after generation 2 objects have been reclaimed for garbage collection.

    En la recolección de elementos no utilizados de servidor, solo un subproceso llama a RestartEE, por lo que el punto de interrupción solo se producirá una vez durante una recolección de elementos no utilizados de generación 2.In server garbage collection, only one thread calls RestartEE, so the breakpoint will occur only once during a generation 2 garbage collection.

Volver al principioBack to top

Procedimientos para comprobar el rendimientoPerformance Check Procedures

En esta sección se describen los procedimientos siguientes para aislar la causa del problema de rendimiento:This section describes the following procedures to isolate the cause of your performance issue:

Para determinar si el problema está provocado por la recolección de elementos no utilizadosTo determine whether the problem is caused by garbage collection
  • Examine los dos contadores de rendimiento de memoria siguientes:Examine the following two memory performance counters:

    • % de tiempo de la GC.% Time in GC. Muestra el porcentaje de tiempo transcurrido que se dedicó a realizar una recolección de elementos no utilizados después del último ciclo de recolección.Displays the percentage of elapsed time that was spent performing a garbage collection after the last garbage collection cycle. Use este contador para determinar si el recolector de elementos no utilizados está dedicando demasiado tiempo a hacer que haya espacio disponible en el montón administrado.Use this counter to determine whether the garbage collector is spending too much time to make managed heap space available. Si el tiempo dedicado a la recolección de elementos no utilizados es relativamente bajo, podría indicar un problema de recursos fuera del montón administrado.If the time spent in garbage collection is relatively low, that could indicate a resource problem outside the managed heap. Puede que este contador no sea exacto cuando se invoca una recolección de elementos no utilizados simultánea o en segundo plano.This counter may not be accurate when concurrent or background garbage collection is involved.

    • Número de bytes totales confirmados.# Total committed Bytes. Muestra la cantidad de memoria virtual confirmada actualmente por el recolector de elementos no utilizados.Displays the amount of virtual memory currently committed by the garbage collector. Use este contador para determinar si la memoria usada por el recolector de elementos no utilizados es una parte excesiva de la memoria que su aplicación emplea.Use this counter to determine whether the memory consumed by the garbage collector is an excessive portion of the memory that your application uses.

    La mayoría de los contadores de rendimiento de memoria se actualizan al final de cada recolección de elementos no utilizados.Most of the memory performance counters are updated at the end of each garbage collection. Por tanto, puede que no reflejen las condiciones actuales sobre las que desea obtener información.Therefore, they may not reflect the current conditions that you want information about.

Para determinar si la excepción de memoria insuficiente está administradaTo determine whether the out-of-memory exception is managed
  1. En WinDbg o en el depurador de Visual Studio con la extensión del depurador de SOS cargada, escriba el comando de impresión de excepciones (pe):In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the print exception (pe) command:

    !pe!pe

    Si la excepción es administrada, se mostrará OutOfMemoryException como el tipo de excepción, como se muestra en el ejemplo siguiente.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. Si el resultado no especifica ninguna excepción, tiene que determinar de qué subproceso procede la excepción de memoria insuficiente.If the output does not specify an exception, you have to determine which thread the out-of-memory exception is from. Escriba el comando siguiente en el depurador para mostrar todos los subprocesos con sus pilas de llamadas:Type the following command in the debugger to show all the threads with their call stacks:

    ~*KB~*kb

    El argumento RaiseTheException indica el subproceso con la pila que tiene llamadas de excepción.The thread with the stack that has exception calls is indicated by the RaiseTheException argument. Este es el objeto de excepción administrado.This is the managed exception object.

    28adfb44 7923918f 5b61f2b4 00000000 5b61f2b4 mscorwks!RaiseTheException+0xa0
    
  3. Puede usar el comando siguiente para volcar las excepciones anidadas.You can use the following command to dump nested exceptions.

    !pe -nested!pe -nested

    Si no encuentra ninguna excepción, la excepción de memoria insuficiente se originó desde código no administrado.If you do not find any exceptions, the out-of-memory exception originated from unmanaged code.

Para determinar cuánta memoria virtual se puede reservarTo determine how much virtual memory can be reserved
  • En WinDbg con la extensión del depurador de SOS cargada, escriba el comando siguiente para obtener la mayor región disponible:In WinDbg with the SOS debugger extension loaded, type the following command to get the largest free region:

    !address -summary!address -summary

    La mayor región disponible se muestra como en el resultado siguiente.The largest free region is displayed as shown in the following output.

    Largest free region: Base 54000000 - Size 0003A980
    

    En este ejemplo, el tamaño de la mayor región disponible es de aproximadamente 24000 KB (3A980 en hexadecimal).In this example, the size of the largest free region is approximately 24000 KB (3A980 in hexadecimal). Esta región es mucho menor que cuando el recolector de elementos no utilizados necesita un segmento.This region is much smaller than what the garbage collector needs for a segment.

    O bien-or-

  • Use el comando vmstat:Use the vmstat command:

    !vmstat!vmstat

    La mayor región disponible es el valor mayor de la columna MAXIMUM, como se muestra en el resultado siguiente.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
    

Para determinar si hay suficiente memoria físicaTo determine whether there is enough physical memory
  1. Inicie el Administrador de tareas de Windows.Start Windows Task Manager.

  2. En la pestaña Rendimiento, busque el valor confirmado.On the Performance tab, look at the committed value. (En Windows 7, busque Asignación (KB) en el grupo Sistema).(In Windows 7, look at Commit (KB) in the System group.)

    Si el Total se aproxima al Límite hay poca memoria física.If the Total is close to the Limit, you are running low on physical memory.

Para determinar cuánta memoria está confirmando el montón administradoTo determine how much memory the managed heap is committing
  • Use el contador de rendimiento de memoria # Total committed bytes para obtener el número de bytes que el montón administrado está confirmando.Use the # Total committed bytes memory performance counter to get the number of bytes that the managed heap is committing. El recolector de elementos no utilizados confirma fragmentos de un segmento a medida que son necesarios, no todos al mismo tiempo.The garbage collector commits chunks on a segment as needed, not all at the same time.

    Nota

    No use el contador de rendimiento # Bytes in all Heaps, ya que no representa el uso de memoria real por parte del montón administrado.Do not use the # Bytes in all Heaps performance counter, because it does not represent actual memory usage by the managed heap. En este valor se incluye el tamaño de una generación y es realmente su tamaño umbral; es decir, el tamaño que induce una recolección de elementos no utilizados si la generación se llena de objetos.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. Por tanto, este valor suele ser cero.Therefore, this value is usually zero.

Para determinar cuánta memoria reserva el montón administradoTo determine how much memory the managed heap reserves
  • Use el contador de rendimiento de memoria # Total reserved bytes.Use the # Total reserved bytes memory performance counter.

    El recolector de elementos no utilizados reserva memoria en segmentos y puede determinar dónde comienza un segmento mediante el comando eeheap.The garbage collector reserves memory in segments, and you can determine where a segment starts by using the eeheap command.

    Importante

    Aunque puede determinar la cantidad de memoria que el recolector de elementos no utilizados asigna a cada segmento, el tamaño del segmento es específico de la implementación y está sujeto a cambios en cualquier momento, incluso en las actualizaciones periódicas.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. La aplicación nunca debe realizar suposiciones sobre el tamaño de un sector determinado ni depender de él, y tampoco debe intentar configurar la cantidad de memoria disponible para las asignaciones de segmentos.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.

  • En WinDbg o en el depurador de Visual Studio con la extensión del depurador de SOS cargada, escriba el comando siguiente:In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the following command:

    !eeheap -gc!eeheap -gc

    El resultado es el siguiente.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)
    

    Las direcciones indicadas por "segment" son las direcciones iniciales de los segmentos.The addresses indicated by "segment" are the starting addresses of the segments.

Para determinar los objetos grandes de la generación 2To determine large objects in generation 2
  • En WinDbg o en el depurador de Visual Studio con la extensión del depurador de SOS cargada, escriba el comando siguiente:In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the following command:

    !dumpheap –stat!dumpheap –stat

    Si el montón administrado es grande, dumpheap puede tardar bastante en finalizar.If the managed heap is big, dumpheap may take a while to finish.

    Puede empezar el análisis por las últimas líneas del resultado, ya que muestran los objetos que usan la mayor parte del espacio.You can start analyzing from the last few lines of the output, because they list the objects that use the most space. Por ejemplo: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
    

    El último objeto mostrado es una cadena y es el que ocupa más espacio.The last object listed is a string and occupies the most space. Puede examinar la aplicación para ver cómo se pueden optimizar los objetos de cadena.You can examine your application to see how your string objects can be optimized. Para ver las cadenas comprendidas entre 150 y 200 bytes, escriba lo siguiente: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

    A continuación se muestra un ejemplo de los resultados.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
    …
    

    Puede ser más eficaz usar un entero en lugar de una cadena para un identificador.Using an integer instead of a string for an ID can be more efficient. Si la misma cadena se está repitiendo miles de veces, considere la posibilidad de asignación al grupo interno de cadenas.If the same string is being repeated thousands of times, consider string interning. Para obtener más información sobre la asignación al grupo interno de cadenas, vea el tema de referencia sobre el método String.Intern.For more information about string interning, see the reference topic for the String.Intern method.

Para determinar las referencias a objetosTo determine references to objects
  • En WinDbg con la extensión del depurador de SOS cargada, escriba el comando siguiente para mostrar las referencias a objetos:In WinDbg with the SOS debugger extension loaded, type the following command to list references to objects:

    !gcroot!gcroot

    -or-

  • Para determinar las referencias para un objeto concreto, incluya la dirección:To determine the references for a specific object, include the address:

    !gcroot 1c37b2ac!gcroot 1c37b2ac

    Las raíces encontradas en pilas pueden ser falsos positivos.Roots found on stacks may be false positives. Para obtener más información, use el comando !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
    

    El comando gcroot puede tardar mucho en finalizar.The gcroot command can take a long time to finish. Todo objeto no reclamado en la recolección de elementos no utilizados es un objeto activo.Any object that is not reclaimed by garbage collection is a live object. Esto implica que alguna raíz se almacena directa o indirectamente en el objeto, por lo que gcroot debe devolver información de ruta de acceso al objeto.This means that some root is directly or indirectly holding onto the object, so gcroot should return path information to the object. Debe examinar los gráficos devueltos y ver por qué todavía se hace referencia a estos objetos.You should examine the graphs returned and see why these objects are still referenced.

Para determinar si se ha ejecutado un finalizadorTo determine whether a finalizer has been run
  • Ejecute un programa de prueba que contenga el código siguiente:Run a test program that contains the following code:

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

    Si la prueba resuelve el problema, significa que el recolector de elementos no utilizados no estaba recuperando objetos porque los finalizadores de esos objetos se habían suspendido.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. El método GC.WaitForPendingFinalizers permite que los finalizadores completen sus tareas y corrige el problema.The GC.WaitForPendingFinalizers method enables the finalizers to complete their tasks, and fixes the problem.

Para determinar si hay objetos en espera de finalizaciónTo determine whether there are objects waiting to be finalized
  1. En WinDbg o en el depurador de Visual Studio con la extensión del depurador de SOS cargada, escriba el comando siguiente:In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the following command:

    !finalizequeue!finalizequeue

    Observe el número de objetos que están listos para la finalización.Look at the number of objects that are ready for finalization. Si el número es elevado, debe examinar por qué estos finalizadores no pueden progresar en absoluto o con la rapidez suficiente.If the number is high, you must examine why these finalizers cannot progress at all or cannot progress fast enough.

  2. Para obtener un resultado de subprocesos, escriba el comando siguiente:To get an output of threads, type the following command:

    threads -specialthreads -special

    Este comando proporciona resultados como el siguiente.This command provides output such as the following.

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

    El subproceso finalizador indica qué finalizador, si hay alguno, se está ejecutando actualmente.The finalizer thread indicates which finalizer, if any, is currently being run. Cuando un subproceso finalizador no está ejecutando ningún finalizador, está esperando un evento para indicarle que haga su trabajo.When a finalizer thread is not running any finalizers, it is waiting for an event to tell it to do its work. La mayoría de las veces verá el subproceso finalizador en este estado porque se ejecuta en THREAD_HIGHEST_PRIORITY y se presupone que termina de ejecutar los finalizadores, si hay alguno, muy rápidamente.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.

Para determinar la cantidad de espacio disponible en el montón administradoTo determine the amount of free space in the managed heap
  • En WinDbg o en el depurador de Visual Studio con la extensión del depurador de SOS cargada, escriba el comando siguiente: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

    Este comando muestra el tamaño total de todos los objetos disponibles en el montón administrado, como se muestra en el ejemplo siguiente.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
    
  • Para determinar el espacio disponible en la generación 0, escriba el comando siguiente para obtener información sobre el consumo de memoria por generación:To determine the free space in generation 0, type the following command for memory consumption information by generation:

    !eeheap -gc!eeheap -gc

    Este comando muestra un resultado similar al siguiente.This command displays output similar to the following. La última línea muestra el segmento efímero.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)
    
  • Calcule el espacio usado por la generación 0:Calculate the space used by generation 0:

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

    El resultado es el siguiente.The result is as follows. La generación 0 ocupa aproximadamente 9 MB.Generation 0 is approximately 9 MB.

    Evaluate expression: 9321848 = 008e3d78
    
  • El comando siguiente vuelca el espacio disponible dentro del intervalo de la generación 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

    El resultado es el siguiente.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
    

    Este resultado muestra que la parte de la generación 0 del montón está usando 9 MB de espacio para los objetos y tiene 7 MB disponibles.This output shows that the generation 0 portion of the heap is using 9 MB of space for objects and has 7 MB free. Este análisis muestra hasta qué punto la generación 0 contribuye a la fragmentación.This analysis shows the extent to which generation 0 contributes to fragmentation. Esta cantidad de uso del montón se debe descontar de la cantidad total como la causa de fragmentación por parte de los objetos de larga duración.This amount of heap usage should be discounted from the total amount as the cause of fragmentation by long-term objects.

Para determinar el número de objetos ancladosTo determine the number of pinned objects
  • En WinDbg o en el depurador de Visual Studio con la extensión del depurador de SOS cargada, escriba el comando siguiente:In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the following command:

    !gchandles!gchandles

    Las estadísticas mostradas incluyen el número de identificadores anclados, como se muestra en el ejemplo siguiente.The statistics displayed includes the number of pinned handles, as the following example shows.

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

Para determinar la duración de una recolección de elementos no utilizadosTo determine the length of time in a garbage collection
  • Examine el contador de rendimiento de memoria % Time in GC.Examine the % Time in GC memory performance counter.

    El valor se calcula usando un tiempo de intervalo de muestra.The value is calculated by using a sample interval time. Como los contadores se actualizan al final de cada recolección de elementos no utilizados, el ejemplo actual tendrá el mismo valor que el ejemplo anterior si no se realizó ninguna recolección durante el intervalo.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.

    Tiempo de recolección se obtiene multiplicando el tiempo de intervalo de muestra por el valor de porcentaje.Collection time is obtained by multiplying the sample interval time with the percentage value.

    Los datos siguientes muestran cuatro intervalos de muestreo de dos segundos para un estudio de 8 segundos.The following data shows four sampling intervals of two seconds, for an 8-second study. Las columnas Gen0, Gen1 y Gen2 muestran el número de recolecciones de elementos no utilizados que se produjeron durante ese intervalo para esa generación.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
    

    Esta información no indica cuándo se produjo la recolección de elementos no utilizados, pero puede determinar el número de recolecciones de elementos no utilizados que se produjeron en un intervalo de tiempo.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. Suponiendo el caso peor, la décima recolección de elementos no utilizados de generación 0 terminó al principio del segundo intervalo y la undécima recolección de elementos no utilizados de generación 0 terminó al final del quinto intervalo.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. El tiempo transcurrido entre el final de la décima recolección de elementos no utilizados y el final de la undécima recolección de elementos no utilizados es de aproximadamente 2 segundos y el contador de rendimiento muestra un 3%, por lo que la duración de la undécima recolección de elementos no utilizados de generación 0 fue de (2 segundos * 3% = 60 ms).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).

    En este ejemplo, hay 5 periodos.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
    

    La segunda recolección de elementos no utilizados de generación 2 se inició durante el tercer intervalo y terminó en el quinto intervalo.The second generation 2 garbage collection started during the third interval and finished at the fifth interval. Suponiendo el caso peor, la última recolección de elementos no utilizados fue de una generación 0 que terminó al principio del segundo intervalo y la recolección de elementos no utilizados de generación 2 terminó al final del quinto intervalo.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. Por tanto, el tiempo transcurrido entre el final de la recolección de elementos no utilizados de generación 0 y el final de la recolección de elementos no utilizados de generación 2 es de 4 segundos.Therefore, the time between the end of the generation 0 garbage collection and the end of the generation 2 garbage collection is 4 seconds. Puesto que el contador % Time in GC muestra un 20%, el tiempo máximo que la recolección de elementos no utilizados de generación 2 podría haber tardado es (4 segundos * 20% = 800 ms).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).

  • También puede determinar la duración de una recolección de elementos no utilizados mediante eventos ETW de recolección de elementos no utilizados y analizar la información para averiguar la duración de la recolección de elementos no utilizados.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.

    Por ejemplo, los datos siguiente muestran una secuencia de eventos que se produjo durante una recolección de elementos no utilizados no simultánea.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
    

    La suspensión del subproceso administrado tardó 26 us (GCSuspendEEEndGCSuspendEEBegin_V1).Suspending the managed thread took 26us (GCSuspendEEEndGCSuspendEEBegin_V1).

    La recolección de elementos no utilizados real tardó 4,8 ms (GCEnd_V1GCStart_V1).The actual garbage collection took 4.8ms (GCEnd_V1GCStart_V1).

    La reanudación de los subprocesos administrados tardó 21 us (GCRestartEEEndGCRestartEEBegin).Resuming the managed threads took 21us (GCRestartEEEndGCRestartEEBegin).

    El resultado siguiente proporciona un ejemplo de recolección de elementos no utilizados en segundo plano, e incluye los campos de proceso, subproceso y evento.The following output provides an example for background garbage collection, and includes the process, thread, and event fields. (No se muestra todos los datos.)(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
    

    El evento GCStart_V1 en 42504816 indica que se trata de una recolección de elementos no utilizados en segundo plano, ya que el último campo es 1.The GCStart_V1 event at 42504816 indicates that this is a background garbage collection, because the last field is 1. Esta se convierte en la recolección de elementos no utilizados númeroThis becomes garbage collection No. 102019.102019.

    El evento GCStart se produce porque se necesita una recolección de elementos no utilizados efímera antes de iniciar una recolección de elementos no utilizados en segundo plano.The GCStart event occurs because there is a need for an ephemeral garbage collection before you start a background garbage collection. Esta se convierte en la recolección de elementos no utilizados númeroThis becomes garbage collection No. 102020.102020.

    En 42514170, la recolección de elementos no utilizados númeroAt 42514170, garbage collection No. 102020 finaliza.102020 finishes. Los subprocesos administrados se reinician en este momento.The managed threads are restarted at this point. Esto se completa en el subproceso 4372, que desencadenó esta recolección de elementos no utilizados en segundo plano.This is completed on thread 4372, which triggered this background garbage collection.

    En el subproceso 4744, se produce una suspensión.On thread 4744, a suspension occurs. Esta es la última vez que la recolección de elementos no utilizados en segundo plano tiene que suspender subprocesos administrados.This is the only time at which the background garbage collection has to suspend managed threads. Esta duración es de aproximadamente 99 ms ((63784407-63685394)/1000).This duration is approximately 99ms ((63784407-63685394)/1000).

    El evento GCEnd para la recolección de elementos no utilizados en segundo plano está en 89931423.The GCEnd event for the background garbage collection is at 89931423. Esto significa que la recolección de elementos no utilizados en segundo plano duró alrededor de 47 segundos ((89931423-42504816)/1000).This means that the background garbage collection lasted for about 47seconds ((89931423-42504816)/1000).

    Mientras los subprocesos administrados se están ejecutando, puede producirse cualquier número de recolecciones de elementos no utilizados efímeras.While the managed threads are running, you can see any number of ephemeral garbage collections occurring.

Para determinar qué desencadenó una recolección de elementos no utilizadosTo determine what triggered a garbage collection
  • En WinDbg o en el depurador de Visual Studio con la extensión del depurador de SOS cargada, escriba el comando siguiente para mostrar todos los subprocesos con sus pilas de llamadas: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

    Este comando muestra un resultado similar al siguiente.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
    

    Si la recolección de elementos no utilizados se produjo por una notificación de memoria insuficiente del sistema operativo, la pila de llamadas es similar, salvo que el subproceso es el subproceso finalizador.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. El subproceso finalizador obtiene una notificación asincrónica de memoria insuficiente e induce la recolección de elementos no utilizados.The finalizer thread gets an asynchronous low memory notification and induces the garbage collection.

    Si la recolección de elementos no utilizados se produjo por la asignación de memoria, la pila aparece de la manera siguiente: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
    

    Un asistente Just-In-Time (JIT_New*) llama finalmente a GCHeap::GarbageCollectGeneration.A just-in-time helper (JIT_New*) eventually calls GCHeap::GarbageCollectGeneration. Si determina que las recolecciones de elementos no utilizados de generación 2 se deben a asignaciones, debe averiguar qué objetos recolecta una recolección de elementos no utilizados de generación 2 y cómo evitarlas.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. Es decir, debe determinar la diferencia entre el inicio y el final de una recolección de elementos no utilizados de generación 2 y los objetos que causaron la recolección de generación 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.

    Por ejemplo, escriba el comando siguiente en el depurador para mostrar el comienzo de una recolección de generación 2:For example, type the following command in the debugger to show the beginning of a generation 2 collection:

    !dumpheap –stat!dumpheap –stat

    Resultado de ejemplo (abreviado para mostrar los objetos que usan más espacio):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
    

    Repita el comando al final de la generación 2:Repeat the command at the end of generation 2:

    !dumpheap –stat!dumpheap –stat

    Resultado de ejemplo (abreviado para mostrar los objetos que usan más espacio):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
    

    Los objetos double[] desaparecieron del final del resultado, lo que significa que se recopilaron.The double[] objects disappeared from the end of the output, which means that they were collected. Estos objetos ocupan aproximadamente 70 MB.These objects account for approximately 70 MB. Los objetos restantes no cambiaron mucho.The remaining objects did not change much. Por tanto, estos objetos double[] eran la razón por la que se produjo esta recolección de elementos no utilizados de generación 2.Therefore, these double[] objects were the reason why this generation 2 garbage collection occurred. El paso siguiente consiste en determinar por qué están allí los objetos double[] y por qué murieron.Your next step is to determine why the double[] objects are there and why they died. Puede preguntar al desarrollador del código la procedencia de estos objetos o puede usar el comando gcroot.You can ask the code developer where these objects came from, or you can use the gcroot command.

Para determinar si el uso elevado de CPU está provocado por la recolección de elementos no utilizadosTo determine whether high CPU usage is caused by garbage collection
  • Correlacione el valor del contador de rendimiento de memoria % Time in GC con el tiempo de proceso.Correlate the % Time in GC memory performance counter value with the process time.

    Si el valor de % Time in GC tiene un pico a la vez que el tiempo de proceso, la recolección de elementos no utilizados está provocando un uso de CPU elevado.If the % Time in GC value spikes at the same time as process time, garbage collection is causing a high CPU usage. De lo contrario, genere un perfil de la aplicación para averiguar dónde se está produciendo el uso elevado.Otherwise, profile the application to find where the high usage is occurring.

Vea tambiénSee also