Garbage Collection e prestazioniGarbage Collection and Performance

Questo argomento descrive i problemi relativi a Garbage Collection e all'uso della memoria.This topic describes issues related to garbage collection and memory usage. Sono incluse informazioni per risolvere i problemi che riguardano l'heap gestito e che descrivono come ridurre al minimo l'effetto di Garbage Collection sulle applicazioni.It addresses issues that pertain to the managed heap and explains how to minimize the effect of garbage collection on your applications. Per ogni problema sono disponibili collegamenti alle procedure che è possibile usare per approfondimenti aggiuntivi.Each issue has links to procedures that you can use to investigate problems.

Di seguito sono elencate le diverse sezioni di questo argomento:This topic contains the following sections:

Strumenti di analisi delle prestazioniPerformance Analysis Tools

Le sezioni seguenti descrivono gli strumenti disponibili per esaminare i problemi relativi a utilizzo della memoria e Garbage Collection.The following sections describe the tools that are available for investigating memory usage and garbage collection issues. Le procedure illustrate più avanti in questo argomento fanno riferimento a questi strumenti.The procedures provided later in this topic refer to these tools.

Contatori delle prestazioni di memoriaMemory Performance Counters

È possibile usare i contatori delle prestazioni per raccogliere dati sulle prestazioni.You can use performance counters to gather performance data. Per istruzioni, vedere Profilatura runtime.For instructions, see Runtime Profiling. La categoria Memoria CLR .NET dei contatori delle prestazioni, descritta in Contatori delle prestazioni in .NET Framework, fornisce informazioni su Garbage Collector.The .NET CLR Memory category of performance counters, as described in Performance Counters in the .NET Framework, provides information about the garbage collector.

Debug con SOSDebugging with SOS

È possibile usare il debugger di Windows (WinDbg) per controllare gli oggetti nell'heap gestito.You can use the Windows Debugger (WinDbg) to inspect objects on the managed heap.

Per installare WinDbg, installare gli strumenti di debug per Windows dalla pagina di download degli strumenti di debug per Windows.To install WinDbg, install Debugging Tools for Windows from the Download Debugging Tools for Windows page.

Eventi ETW di Garbage CollectionGarbage Collection ETW Events

Event Tracing for Windows (ETW) è un sistema di traccia che integra il supporto per profilatura e debug offerto da .NET Framework.Event tracing for Windows (ETW) is a tracing system that supplements the profiling and debugging support provided by the .NET Framework. A partire da .NET Framework 4.NET Framework 4, gli eventi ETW di Garbage Collection acquisiscono informazioni utili per l'analisi dell'heap gestito da un punto di vista statistico.Starting with the .NET Framework 4.NET Framework 4, garbage collection ETW events capture useful information for analyzing the managed heap from a statistical point of view. Ad esempio, l'evento GCStart_V1, generato quando sta per verificarsi un'operazione di Garbage Collection, fornisce le informazioni seguenti:For example, the GCStart_V1 event, which is raised when a garbage collection is about to occur, provides the following information:

  • Generazione di oggetti raccolta.Which generation of objects is being collected.

  • Che cosa ha attivato l'operazione di Garbage Collection.What triggered the garbage collection.

  • Tipo di Garbage Collection (simultanea o non simultanea).Type of garbage collection (concurrent or not concurrent).

La registrazione degli eventi ETW è efficiente e non maschera alcun problema di prestazioni associato a Garbage Collection.ETW event logging is efficient and will not mask any performance problems associated with garbage collection. Un processo può fornire i propri eventi insieme agli eventi ETW.A process can provide its own events in conjunction with ETW events. Una volta registrati, sia gli eventi dell'applicazione sia quelli di Garbage Collection possono essere correlati per determinare come e quando si verificano problemi relativi all'heap.When logged, both the application's events and the garbage collection events can be correlated to determine how and when heap problems occur. Ad esempio, un'applicazione server può fornire eventi all'inizio e alla fine di una richiesta client.For example, a server application could provide events at the start and end of a client request.

API di profilaturaThe Profiling API

Le interfacce di profilatura Common Language Runtime (CLR) forniscono informazioni dettagliate sugli oggetti interessati durante l'operazione di Garbage Collection.The common language runtime (CLR) profiling interfaces provide detailed information about the objects that were affected during garbage collection. Un profiler può ricevere una notifica all'inizio o alla fine di un'operazione di Garbage CollectionA profiler can be notified when a garbage collection starts and ends. e può fornire report sugli oggetti nell'heap gestito, inclusa un'identificazione degli oggetti in ogni generazione.It can provide reports about the objects on the managed heap, including an identification of objects in each generation. Per altre informazioni, vedere Cenni preliminari sulla profilatura.For more information, see Profiling Overview.

I profiler possono fornire informazioni complete.Profilers can provide comprehensive information. Tuttavia, i profiler complessi possono potenzialmente modificare il comportamento di un'applicazione.However, complex profilers can potentially modify an application's behavior.

Monitoraggio delle risorse del dominio applicazioneApplication Domain Resource Monitoring

A partire da .NET Framework 4.NET Framework 4, il monitoraggio delle risorse del dominio applicazione permette agli host di monitorare l'utilizzo di CPU e memoria da parte del dominio applicazione.Starting with the .NET Framework 4.NET Framework 4, Application domain resource monitoring (ARM) enables hosts to monitor CPU and memory usage by application domain. Per altre informazioni, vedere Monitoraggio delle risorse del dominio applicazione.For more information, see Application Domain Resource Monitoring.

Torna all'inizioBack to top

Risoluzione dei problemi relativi alle prestazioniTroubleshooting Performance Issues

Il primo passaggio consiste nel determinare se il problema è in realtà causato dall'operazione di Garbage Collection.The first step is to determine whether the issue is actually garbage collection. In questo caso, selezionare una delle voci nell'elenco seguente per risolvere il problema.If you determine that it is, select from the following list to troubleshoot the problem.

Problema: viene generata un'eccezione di memoria esauritaIssue: An Out-of-Memory Exception Is Thrown

Esistono due casi legittimi per la generazione di un'eccezione OutOfMemoryException gestita:There are two legitimate cases for a managed OutOfMemoryException to be thrown:

  • Esaurimento della memoria virtuale.Running out of virtual memory.

    Garbage Collector alloca memoria dal sistema in segmenti di dimensioni predeterminate.The garbage collector allocates memory from the system in segments of a pre-determined size. Se un'allocazione richiede un segmento aggiuntivo, ma non è più disponibile un blocco contiguo libero nello spazio di memoria virtuale del processo, l'allocazione per l'heap gestito non riesce.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.

  • Mancanza di memoria fisica sufficiente da allocare.Not having enough physical memory to allocate.

Controlli delle prestazioniPerformance checks
Determinare se l'eccezione di memoria esaurita è gestita.Determine whether the out-of-memory exception is managed.

Determinare la quantità di memoria virtuale che è possibile riservare.Determine how much virtual memory can be reserved.

Determinare se è disponibile memoria fisica sufficiente.Determine whether there is enough physical memory.

Se si determina che l'eccezione non è legittima, contattare il Supporto tecnico Microsoft avendo a portata di mano le informazioni seguenti:If you determine that the exception is not legitimate, contact Microsoft Customer Service and Support with the following information:

  • Stack con l'eccezione di memoria esaurita gestita.The stack with the managed out-of-memory exception.

  • Dump di memoria completo.Full memory dump.

  • Dati che dimostrano che non si tratta di un'eccezione di memoria esaurita legittima, inclusi quelli che indicano che la memoria fisica o virtuale non è la causa del 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: il processo usa una quantità eccessiva di memoriaIssue: The Process Uses Too Much Memory

Un presupposto comune è che l'uso della memoria visualizzato nella scheda Prestazioni di Gestione attività di Windows può indicare quando viene usata una quantità eccessiva di 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. Tuttavia, queste informazioni visualizzate riguardano il set di lavoro e non l'utilizzo della memoria virtuale.However, that display pertains to the working set; it does not provide information about virtual memory usage.

Se si determina che il problema è causato dall'heap gestito, è necessario misurare l'heap gestito nel tempo per stabilire gli eventuali modelli.If you determine that the issue is caused by the managed heap, you must measure the managed heap over time to determine any patterns.

Se si determina che il problema non è causato dall'heap gestito, è necessario usare il debug nativo.If you determine that the problem is not caused by the managed heap, you must use native debugging.

Controlli delle prestazioniPerformance checks
Determinare la quantità di memoria virtuale che è possibile riservare.Determine how much virtual memory can be reserved.

Determinare la quantità di memoria di cui l'heap gestito esegue il commit.Determine how much memory the managed heap is committing.

Determinare la quantità di memoria riservata dall'heap gestito.Determine how much memory the managed heap reserves.

Determinare gli oggetti di grandi dimensioni nella generazione 2.Determine large objects in generation 2.

Determinare i riferimenti agli oggetti.Determine references to objects.

Problema: Garbage Collector non recupera gli oggetti in modo abbastanza veloceIssue: The Garbage Collector Does Not Reclaim Objects Fast Enough

Quando sembra che gli oggetti non vengano recuperati nel modo previsto per l'operazione di Garbage Collection, è necessario determinare se vi siano riferimenti sicuri a tali oggetti.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.

È possibile riscontrare questo problema anche se non è stata eseguita alcuna operazione di Garbage Collection per la generazione che contiene un oggetto inutilizzato, a indicare che il finalizzatore per tale oggetto inutilizzato non è stato eseguito.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. Ad esempio, ciò è possibile quando si esegue un'applicazione apartment a thread singolo (STA, Single-Threaded Apartment) e il thread che gestisce la coda del finalizzatore non può eseguire chiamate al suo interno.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.

Controlli delle prestazioniPerformance checks
Controllare i riferimenti agli oggetti.Check references to objects.

Determinare se è stato eseguito un finalizzatore.Determine whether a finalizer has been run.

Determinare se sono presenti oggetti in attesa di essere finalizzati.Determine whether there are objects waiting to be finalized.

Problema: l'heap gestito è troppo frammentatoIssue: The Managed Heap Is Too fragmented

Il livello di frammentazione viene calcolato come percentuale di spazio libero rispetto alla memoria totale allocata per la generazione.The fragmentation level is calculated as the ratio of free space over the total allocated memory for the generation. Per la generazione 2, un livello accettabile di frammentazione non è maggiore del 20%.For generation 2, an acceptable level of fragmentation is no more than 20%. Poiché la generazione 2 può assumere dimensioni molto grandi, il rapporto di frammentazione è più importante del valore assoluto.Because generation 2 can get very big, the ratio of fragmentation is more important than the absolute value.

La disponibilità di una quantità elevata di spazio libero nella generazione 0 non costituisce un problema, perché si tratta della generazione in cui vengono allocati nuovi oggetti.Having lots of free space in generation 0 is not a problem because this is the generation where new objects are allocated.

La frammentazione si verifica sempre nell'heap oggetti grandi in quanto non viene compattato.Fragmentation always occurs in the large object heap because it is not compacted. Gli oggetti liberi adiacenti vengono naturalmente compressi in un unico spazio per soddisfare le richieste di allocazione di oggetti grandi.Free objects that are adjacent are naturally collapsed into a single space to satisfy large object allocation requests.

La frammentazione può diventare un problema nella generazione 1 e nella generazione 2.Fragmentation can become a problem in generation 1 and generation 2. Se in queste generazioni è disponibile una quantità elevata di spazio libero dopo un'operazione di Garbage Collection, potrebbe essere necessario modificare l'utilizzo degli oggetti di un'applicazione e provare a eseguire una nuova valutazione della durata degli oggetti a lungo termine.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.

Il blocco eccessivo di oggetti può aumentare la frammentazione.Excessive pinning of objects can increase fragmentation. Se la frammentazione è elevata, potrebbe essere bloccato un numero eccessivo di oggetti.If fragmentation is high, too many objects could be pinned.

Se la frammentazione della memoria virtuale impedisce a Garbage Collector di aggiungere segmenti, la causa può essere una delle seguenti:If fragmentation of virtual memory is preventing the garbage collector from adding segments, the causes could be one of the following:

  • Caricamento e scaricamento frequenti di molti assembly di piccole dimensioni.Frequent loading and unloading of many small assemblies.

  • Presenza di troppi riferimenti a oggetti COM durante l'interoperabilità con codice non gestito.Holding too many references to COM objects when interoperating with unmanaged code.

  • Creazione di oggetti temporanei di grandi dimensioni, che fa sì che l'heap grandi oggetti allochi e liberi frequentemente segmenti di heap.Creation of large transient objects, which causes the large object heap to allocate and free heap segments frequently.

    Quando si ospita CLR, un'applicazione può richiedere che Garbage Collector ne mantenga i segmenti.When hosting the CLR, an application can request that the garbage collector retain its segments. In questo modo, viene ridotta la frequenza delle allocazioni di segmenti.This reduces the frequency of segment allocations. A questo scopo, viene usato il contrassegno STARTUP_HOARD_GC_VM nell'Enumerazione STARTUP_FLAGS.This is accomplished by using the STARTUP_HOARD_GC_VM flag in the STARTUP_FLAGS Enumeration.

Controlli delle prestazioniPerformance checks
Determinare la quantità di spazio libero nell'heap gestito.Determine the amount of free space in the managed heap.

Determinare il numero di oggetti bloccati.Determine the number of pinned objects.

Se si ritiene che non sussista una causa legittima per la frammentazione, contattare il Supporto tecnico Microsoft.If you think that there is no legitimate cause for the fragmentation, contact Microsoft Customer Service and Support.

Problema: le pause di Garbage Collection sono troppo prolungateIssue: Garbage Collection Pauses Are Too Long

Poiché le operazioni di Garbage Collection avvengono in tempo reale "soft", un'applicazione deve essere in grado di tollerare alcune pause.Garbage collection operates in soft real time, so an application must be able to tolerate some pauses. Un criterio che determina l'esecuzione in tempo reale "soft" è che il 95% delle operazioni deve terminare in tempo.A criterion for soft real time is that 95% of the operations must finish on time.

Nelle operazioni di Garbage Collection simultanee, i thread gestiti possono essere eseguiti durante una raccolta, che significa che le pause sono minime.In concurrent garbage collection, managed threads are allowed to run during a collection, which means that pauses are very minimal.

Poiché le operazioni di Garbage Collection effimere (generazioni 0 e 1) durano solo pochi millisecondi, la riduzione delle pause non è in genere possibile.Ephemeral garbage collections (generations 0 and 1) last only a few milliseconds, so decreasing pauses is usually not feasible. Tuttavia, è possibile ridurre le pause nelle raccolte di generazione 2 modificando il modello delle richieste di allocazione da parte di un'applicazione.However, you can decrease the pauses in generation 2 collections by changing the pattern of allocation requests by an application.

Un altro metodo, più accurato, consiste nell'usare gli eventi ETW di Garbage Collection.Another, more accurate, method is to use garbage collection ETW events. È possibile individuare gli intervalli di tempo per le raccolte aggiungendo le differenze dei timestamp per una sequenza di eventi.You can find the timings for collections by adding the time stamp differences for a sequence of events. L'intera sequenza di raccolta include la sospensione del motore di esecuzione, l'operazione di Garbage Collection stessa e la ripresa del motore di esecuzione.The whole collection sequence includes suspension of the execution engine, the garbage collection itself, and the resumption of the execution engine.

È possibile usare le notifiche di Garbage Collection per determinare se in un server sta per essere eseguita una raccolta di generazione 2 e se le richieste di reindirizzamento a un altro server potrebbero risolvere eventuali problemi relativi alle pause.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.

Controlli delle prestazioniPerformance checks
Determinare la durata di un'operazione di Garbage Collection.Determine the length of time in a garbage collection.

Determinare la causa di un'operazione di Garbage Collection.Determine what caused a garbage collection.

Problema: la generazione 0 ha dimensioni eccessiveIssue: Generation 0 Is Too Big

È probabile che la generazione 0 abbia un numero maggiore di oggetti in un sistema a 64 bit, in particolare se si usa un'operazione di Garbage Collection per server invece che per workstation.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. Ciò è dovuto al fatto che la soglia per attivare un'operazione di Garbage Collection di generazione 0 è maggiore in questi ambienti e le raccolte di generazione 0 possono essere molto più grandi.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. Le prestazioni sono migliori quando un'applicazione alloca molta memoria prima dell'attivazione di un'operazione di Garbage Collection.Performance is improved when an application allocates more memory before a garbage collection is triggered.

Problema: l'utilizzo della CPU durante un'operazione di Garbage Collection è eccessivoIssue: CPU Usage During a Garbage Collection Is Too High

L'utilizzo della CPU durante un'operazione di Garbage Collection è elevato.CPU usage will be high during a garbage collection. Se il periodo di tempo del processo è significativo in un'operazione di Garbage Collection, il numero di raccolte è troppo frequente oppure la raccolta dura troppo a lungo.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 frequenza di allocazione di oggetti maggiore nell'heap gestito fa sì che le operazioni di Garbage Collection avvengano più spesso.An increased allocation rate of objects on the managed heap causes garbage collection to occur more frequently. La riduzione della frequenza di allocazione riduce anche la frequenza delle operazioni di Garbage Collection.Decreasing the allocation rate reduces the frequency of garbage collections.

È possibile monitorare le frequenze di allocazione usando il contatore delle prestazioni Allocated Bytes/second.You can monitor allocation rates by using the Allocated Bytes/second performance counter. Per altre informazioni, vedere Contatori delle prestazioni in .NET Framework.For more information, see Performance Counters in the .NET Framework.

La durata di una raccolta è principalmente un fattore del numero di oggetti rimanenti in seguito all'allocazione.The duration of a collection is primarily a factor of the number of objects that survive after allocation. Garbage Collector deve usare una quantità elevata di memoria se restano molti oggetti da raccogliere.The garbage collector must go through a large amount of memory if many objects remain to be collected. L'attività di compattazione degli oggetti rimanenti richiede molto tempo.The work to compact the survivors is time-consuming. Per determinare quanti oggetti sono stati gestiti durante una raccolta, impostare un punto di interruzione nel debugger alla fine di un'operazione di Garbage Collection per una generazione specificata.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.

Controlli delle prestazioniPerformance checks
Determinare se l'utilizzo elevato della CPU è causato dall'operazione di Garbage Collection.Determine if high CPU usage is caused by garbage collection.

Impostare un punto di interruzione alla fine dell'operazione di Garbage Collection.Set a breakpoint at the end of garbage collection.

Torna all'inizioBack to top

Linee guida per la risoluzione dei problemiTroubleshooting Guidelines

Questa sezione contiene linee guida da tenere presenti quando si inizia a esaminare i problemi.This section describes guidelines that you should consider as you begin your investigations.

Garbage Collection per workstation o per serverWorkstation or Server Garbage Collection

Determinare se il tipo di Garbage Collection usato è quello corretto.Determine if you are using the correct type of garbage collection. Se l'applicazione usa più thread e istanze di oggetto, usare Garbage Collection per server anziché per workstation.If your application uses multiple threads and object instances, use server garbage collection instead of workstation garbage collection. Un'operazione di Garbage Collection per server viene eseguita su più thread, mentre una per workstation richiede l'esecuzione di più istanze di un'applicazione nei rispettivi thread di Garbage Collection e che queste competano per il tempo di 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.

Un'applicazione associata a un carico ridotto e che esegue raramente attività in background, ad esempio un servizio, può usare un'operazione di Garbage Collection per workstation con le operazioni di Garbage Collection simultanee disattivate.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.

Quando misurare le dimensioni dell'heap gestitoWhen to Measure the Managed Heap Size

Se non si usa un profiler, è necessario definire un modello di misurazione coerente per diagnosticare con efficacia i problemi di prestazioni.Unless you are using a profiler, you will have to establish a consistent measuring pattern to effectively diagnose performance issues. Per definire una pianificazione, considerare i punti seguenti:Consider the following points to establish a schedule:

  • Se si esegue una misurazione dopo un'operazione di Garbage Collection di generazione 2, l'intero heap gestito sarò libero da oggetti inutilizzati.If you measure after a generation 2 garbage collection, the entire managed heap will be free of garbage (dead objects).

  • Se si esegue una misurazione immediatamente dopo un'operazione di Garbage Collection di generazione 0, gli oggetti nelle generazioni 1 e 2 non verranno ancora raccolti.If you measure immediately after a generation 0 garbage collection, the objects in generations 1 and 2 will not be collected yet.

  • Se si esegue una misurazione immediatamente prima di un'operazione di Garbage Collection, è necessario misurare tutta l'allocazione possibile prima dell'avvio dell'operazione di Garbage Collection.If you measure immediately before a garbage collection, you will measure as much allocation as possible before the garbage collection starts.

  • La misurazione durante un'operazione di Garbage Collection è problematica, perché le strutture di dati di Garbage Collector non sono in uno stato valido per l'attraversamento e potrebbero non essere in grado di fornire i risultati completi.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. Si tratta di un comportamento correlato alla progettazione.This is by design.

  • Quando si usa un'operazione di Garbage Collection per workstation con un'operazione di Garbage Collection simultanea, gli oggetti recuperati non vengono compattati e di conseguenza le dimensioni dell'heap possono essere uguali o maggiori (la frammentazione può farle apparire maggiori).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).

  • Un'operazione di Garbage Collection simultanea nella generazione 2 viene ritardata quando il carico di memoria fisica è troppo elevato.Concurrent garbage collection on generation 2 is delayed when the physical memory load is too high.

La procedura seguente descrive come impostare un punto di interruzione per misurare l'heap gestito.The following procedure describes how to set a breakpoint so that you can measure the managed heap.

Per impostare un punto di interruzione alla fine dell'operazione di Garbage CollectionTo set a breakpoint at the end of garbage collection
  • In WinDbg con l'estensione del debugger SOS caricata, digitare il comando seguente: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'"

    dove GcCondemnedGeneration è impostato sulla generazione desiderata.where GcCondemnedGeneration is set to the desired generation. Questo comando richiede simboli privati.This command requires private symbols.

    Il comando forza un'interruzione se RestartEE viene eseguito dopo il recupero di oggetti di generazione 2 per l'operazione di Garbage Collection.This command forces a break if RestartEE is executed after generation 2 objects have been reclaimed for garbage collection.

    In un'operazione di Garbage Collection per server, solo un thread chiama RestartEE, in modo che il punto di interruzione si verifica solo una volta durante un'operazione di Garbage Collection di generazione 2.In server garbage collection, only one thread calls RestartEE, so the breakpoint will occur only once during a generation 2 garbage collection.

Torna all'inizioBack to top

Procedure di controllo delle prestazioniPerformance Check Procedures

Questa sezione descrive le procedure per isolare la causa del problema di prestazioni:This section describes the following procedures to isolate the cause of your performance issue:

Per determinare se il problema è causato da Garbage CollectionTo determine whether the problem is caused by garbage collection
  • Esaminare i due contatori delle prestazioni della memoria seguenti:Examine the following two memory performance counters:

    • Percentuale tempo in GC.% Time in GC. Visualizza la percentuale di tempo trascorso, impiegato per l'esecuzione di un'operazione di Garbage Collection dopo l'ultimo ciclo di Garbage Collection.Displays the percentage of elapsed time that was spent performing a garbage collection after the last garbage collection cycle. Usare questo contatore per determinare se Garbage Collector sta impiegando troppo tempo per rendere disponibile lo spazio dell'heap gestito.Use this counter to determine whether the garbage collector is spending too much time to make managed heap space available. Se il tempo impiegato nell'operazione di Garbage Collection è relativamente ridotto, ciò può indicare un problema di risorse all'esterno dell'heap gestito.If the time spent in garbage collection is relatively low, that could indicate a resource problem outside the managed heap. Questo contatore potrebbe non essere accurato se sono interessate operazioni di Garbage Collection simultanee o in background.This counter may not be accurate when concurrent or background garbage collection is involved.

    • N. totale di byte con commit.# Total committed Bytes. Visualizza la quantità di memoria virtuale di cui Garbage Collector ha attualmente eseguito il commit.Displays the amount of virtual memory currently committed by the garbage collector. Usare questo contatore per determinare se la memoria usata da Garbage Collector è una parte eccessiva della memoria usata dall'applicazione.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 maggior parte dei contatori delle prestazioni della memoria viene aggiornata alla fine di ogni operazione di Garbage Collection.Most of the memory performance counters are updated at the end of each garbage collection. Di conseguenza, i contatori potrebbero non riflettere le attuali condizioni su cui si vuole ottenere informazioni.Therefore, they may not reflect the current conditions that you want information about.

Per determinare se l'eccezione di memoria esaurita è gestitaTo determine whether the out-of-memory exception is managed
  1. Nel debugger WinDbg o di Visual Studio con l'estensione del debugger SOS caricata, digitare il comando di stampa dell'eccezione (pe):In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the print exception (pe) command:

    !pe!pe

    Se l'eccezione è gestita, OutOfMemoryException viene visualizzato come tipo di eccezione, come mostrato nell'esempio seguente.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. Se l'output non specifica un'eccezione, è necessario determinare il thread da cui proviene l'eccezione di memoria esaurita.If the output does not specify an exception, you have to determine which thread the out-of-memory exception is from. Digitare il comando seguente nel debugger per mostrare tutti i thread con i rispettivi stack di chiamate:Type the following command in the debugger to show all the threads with their call stacks:

    ~*kb~*kb

    Il thread con lo stack che include le chiamate dell'eccezione è indicato dall'argomento RaiseTheException.The thread with the stack that has exception calls is indicated by the RaiseTheException argument. Si tratta dell'oggetto eccezione gestita.This is the managed exception object.

    28adfb44 7923918f 5b61f2b4 00000000 5b61f2b4 mscorwks!RaiseTheException+0xa0   
    
  3. È possibile usare il comando seguente per eseguire il dump delle eccezioni annidate:You can use the following command to dump nested exceptions.

    !pe -nested!pe -nested

    Se non si trova alcuna eccezione, l'eccezione di memoria esaurita proviene da codice non gestito.If you do not find any exceptions, the out-of-memory exception originated from unmanaged code.

Per determinare la quantità di memoria virtuale che è possibile riservareTo determine how much virtual memory can be reserved
  • In WinDbg con l'estensione del debugger SOS caricata, digitare il comando seguente per ottenere l'area libera più grande:In WinDbg with the SOS debugger extension loaded, type the following command to get the largest free region:

    !address -summary!address -summary

    L'area libera più grande viene visualizzata come indicato nell'output seguente.The largest free region is displayed as shown in the following output.

    Largest free region: Base 54000000 - Size 0003A980  
    

    In questo esempio la dimensione dell'area libera più grande è circa 24000 KB (3A980 in formato esadecimale).In this example, the size of the largest free region is approximately 24000 KB (3A980 in hexadecimal). Questa area è molto minore rispetto alle dimensioni richieste da Garbage Collector per un segmento.This region is much smaller than what the garbage collector needs for a segment.

    oppure-or-

  • Utilizzare il comando vmstat:Use the vmstat command:

    !vmstat!vmstat

    L'area libera più grande corrisponde al valore maggiore nella colonna MAXIMUM, come indicato nell'output seguente.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  
    

Per determinare se è disponibile memoria fisica sufficienteTo determine whether there is enough physical memory
  1. Avviare Gestione risorse di Windows.Start Windows Task Manager.

  2. Nella scheda Prestazioni osservare il valore di cui è stato eseguito il commit.On the Performance tab, look at the committed value. In Windows 7 osservare il valore di Commit (KB) nel gruppo Sistema.(In Windows 7, look at Commit (KB) in the System group.)

    Se il valore specificato in Totale si avvicina al valore di Limite, la memoria fisica è insufficiente.If the Total is close to the Limit, you are running low on physical memory.

Per determinare la quantità di memoria di cui l'heap gestito esegue il commitTo determine how much memory the managed heap is committing
  • Usare il contatore delle prestazioni della memoria # Total committed bytes per ottenere il numero di byte di cui l'heap gestito sta eseguendo il commit.Use the # Total committed bytes memory performance counter to get the number of bytes that the managed heap is committing. Garbage Collector esegue il commit dei blocchi in un segmento nel modo necessario e non di tutti allo stesso tempo.The garbage collector commits chunks on a segment as needed, not all at the same time.

    Nota

    Non usare il contatore delle prestazioni # Bytes in all Heaps, perché non rappresenta l'effettivo utilizzo della memoria da parte dell'heap gestito.Do not use the # Bytes in all Heaps performance counter, because it does not represent actual memory usage by the managed heap. La dimensione di una generazione è inclusa in questo valore e corrisponde i n realtà alla dimensione della soglia, ovvero la dimensione che provoca un'operazione di Garbage Collection se la generazione include molti oggetti.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. Di conseguenza, questo valore è in genere uguale a zero.Therefore, this value is usually zero.

Per determinare la quantità di memoria riservata dall'heap gestitoTo determine how much memory the managed heap reserves
  • Usare il contatore delle prestazioni della memoria # Total reserved bytes.Use the # Total reserved bytes memory performance counter.

    Garbage Collector riserva memoria in segmenti ed è possibile determinare il punto di inizio di un segmento usando il comando eeheap.The garbage collector reserves memory in segments, and you can determine where a segment starts by using the eeheap command.

    Importante

    Benché sia possibile determinare la quantità di memoria allocata da Garbage Collector per ogni segmento, le dimensioni dei segmenti sono specifiche dell'implementazione e soggette a modifiche, tra cui aggiornamenti periodici, in qualsiasi momento.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. L'applicazione non deve dare per scontata o dipendere da una particolare dimensione del segmento, né provare a configurare la quantità di memoria disponibile per le allocazioni di segmenti.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.

  • Nel debugger WinDbg o di Visual Studio con l'estensione del debugger SOS caricata, digitare il comando seguente:In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the following command:

    !eeheap -gc!eeheap -gc

    Il risultato è il seguente.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)  
    

    Gli indirizzi indicati da "segment" sono gli indirizzi iniziali dei segmenti.The addresses indicated by "segment" are the starting addresses of the segments.

Per determinare gli oggetti di grandi dimensioni nella generazione 2To determine large objects in generation 2
  • Nel debugger WinDbg o di Visual Studio con l'estensione del debugger SOS caricata, digitare il comando seguente:In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the following command:

    !dumpheap –stat!dumpheap –stat

    Se l'heap gestito è di grandi dimensioni, il completamento di dumpheap può richiedere alcuni minuti.If the managed heap is big, dumpheap may take a while to finish.

    È possibile iniziare l'analisi dalle ultime righe dell'output, perché elencano gli oggetti che usano la maggior parte dello spazio.You can start analyzing from the last few lines of the output, because they list the objects that use the most space. Ad esempio: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  
    

    L'ultimo oggetto elencato è una stringa e occupa la maggior parte dello spazio.The last object listed is a string and occupies the most space. È possibile esaminare l'applicazione per determinare come ottimizzare gli oggetti stringa.You can examine your application to see how your string objects can be optimized. Per visualizzare le stringhe comprese tra 150 e 200 byte, digitare: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

    Di seguito viene riportato un esempio dei risultati.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  
    …  
    

    L'uso di un numero intero invece di una stringa per un ID può rivelarsi più efficiente.Using an integer instead of a string for an ID can be more efficient. Se la stessa stringa è ripetuta migliaia di volte, provare ad applicare l'inserimento di stringhe.If the same string is being repeated thousands of times, consider string interning. Per altre informazioni sull'inserimento di stringhe, vedere l'argomento di riferimento per il metodo String.Intern.For more information about string interning, see the reference topic for the String.Intern method.

Per determinare i riferimenti agli oggettiTo determine references to objects
  • In WinDbg con l'estensione del debugger SOS caricata, digitare il comando seguente per elencare i riferimenti agli oggetti:In WinDbg with the SOS debugger extension loaded, type the following command to list references to objects:

    !gcroot!gcroot

    -or-

  • Per determinare i riferimenti per un oggetto specifico, includere l'indirizzo:To determine the references for a specific object, include the address:

    !gcroot 1c37b2ac!gcroot 1c37b2ac

    Le radici trovate negli stack possono essere falsi positivi.Roots found on stacks may be false positives. Per altre informazioni, usare il 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  
    

    Il completamento del comando gcroot può richiedere molto tempo.The gcroot command can take a long time to finish. Qualsiasi oggetto non recuperato dall'operazione di Garbage Collection è un oggetto attivo.Any object that is not reclaimed by garbage collection is a live object. Questo significa che una radice mantiene direttamente o indirettamente l'oggetto, motivo per cui gcroot deve restituire le informazioni sul percorso dell'oggetto.This means that some root is directly or indirectly holding onto the object, so gcroot should return path information to the object. È consigliabile esaminare i grafici restituiti e determinare perché viene ancora fatto riferimento a questi oggetti.You should examine the graphs returned and see why these objects are still referenced.

Per determinare se è stato eseguito un finalizzatoreTo determine whether a finalizer has been run
  • Eseguire un programma di test contenente il codice seguente:Run a test program that contains the following code:

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

    Se il test risolve il problema, significa che Garbage Collector non ha recuperato gli oggetti perché il finalizzatore per tali oggetti è stato sospeso.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. Il metodo GC.WaitForPendingFinalizers permette ai finalizzatori di completare le rispettive attività e corregge il problema.The GC.WaitForPendingFinalizers method enables the finalizers to complete their tasks, and fixes the problem.

Per determinare se sono presenti oggetti in attesa di essere finalizzatiTo determine whether there are objects waiting to be finalized
  1. Nel debugger WinDbg o di Visual Studio con l'estensione del debugger SOS caricata, digitare il comando seguente:In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the following command:

    !finalizequeue!finalizequeue

    Osservare il numero di oggetti pronti per la finalizzazione.Look at the number of objects that are ready for finalization. Se il numero è elevato, è necessario esaminare il motivo per cui i finalizzatori non possono continuare del tutto o in modo abbastanza veloce.If the number is high, you must examine why these finalizers cannot progress at all or cannot progress fast enough.

  2. Per ottenere un output dei thread, digitare il comando seguente:To get an output of threads, type the following command:

    threads -specialthreads -special

    Questo comando genera un output simile al seguente.This command provides output such as the following.

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

    Il thread del finalizzatore indica quale finalizzatore, se presente, è attualmente in esecuzione.The finalizer thread indicates which finalizer, if any, is currently being run. Quando un thread del finalizzatore non esegue alcun finalizzatore, è in attesa di un evento che indichi di eseguire il lavoro.When a finalizer thread is not running any finalizers, it is waiting for an event to tell it to do its work. Nella maggior parte dei casi il thread del finalizzatore verrà visualizzato in questo stato, perché viene eseguito in THREAD_HIGHEST_PRIORITY e si suppone che completi l'esecuzione dei finalizzatori, se presenti, molto rapidamente.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.

Per determinare la quantità di spazio libero nell'heap gestitoTo determine the amount of free space in the managed heap
  • Nel debugger WinDbg o di Visual Studio con l'estensione del debugger SOS caricata, digitare il comando seguente: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

    Questo comando visualizza le dimensioni totali di tutti gli oggetti liberi nell'heap gestito, come mostrato nell'esempio seguente.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  
    
  • Per determinare lo spazio libero nella generazione 0, digitare il comando seguente per informazioni sull'utilizzo della memoria da parte della generazione:To determine the free space in generation 0, type the following command for memory consumption information by generation:

    !eeheap -gc!eeheap -gc

    Questo comando genera un output simile al seguente.This command displays output similar to the following. L'ultima riga mostra il segmento effimero.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)  
    
  • Calcolare lo spazio usato dalla generazione 0:Calculate the space used by generation 0:

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

    Il risultato è il seguente.The result is as follows. La generazione 0 è di circa 9 MB.Generation 0 is approximately 9 MB.

    Evaluate expression: 9321848 = 008e3d78  
    
  • Il comando seguente esegue il dump dello spazio libero all'interno dell'intervallo della generazione 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

    Il risultato è il seguente.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  
    

    Questo output mostra che la parte di generazione 0 dell'heap usa 9 MB di spazio per gli oggetti e ha 7 MB di spazio libero.This output shows that the generation 0 portion of the heap is using 9 MB of space for objects and has 7 MB free. Questa analisi mostra in quale misura la generazione 0 contribuisce alla frammentazione.This analysis shows the extent to which generation 0 contributes to fragmentation. Questa quantità di utilizzo dell'heap deve essere sottratta dalla quantità locale come causa di frammentazione da parte di oggetti a lungo termine.This amount of heap usage should be discounted from the total amount as the cause of fragmentation by long-term objects.

Per determinare il numero di oggetti bloccatiTo determine the number of pinned objects
  • Nel debugger WinDbg o di Visual Studio con l'estensione del debugger SOS caricata, digitare il comando seguente:In the WinDbg or Visual Studio debugger with the SOS debugger extension loaded, type the following command:

    !gchandles!gchandles

    Le statistiche visualizzate includono il numero di handle bloccati, come indicato nell'esempio seguente.The statistics displayed includes the number of pinned handles, as the following example shows.

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

Per determinare il periodo di tempo in un'operazione di Garbage CollectionTo determine the length of time in a garbage collection
  • Esaminare il contatore delle prestazioni della memoria % Time in GC.Examine the % Time in GC memory performance counter.

    Il valore viene calcolato usando un intervallo di tempo di esempio.The value is calculated by using a sample interval time. Poiché i contatori vengono aggiornati alla fine di ogni operazione di Garbage Collection, l'esempio corrente avrà lo stesso valore di quello precedente se durante l'intervallo non è stata eseguita alcuna raccolta.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.

    La durata della raccolta viene ottenuta moltiplicando l'intervallo di esempio per il valore percentuale.Collection time is obtained by multiplying the sample interval time with the percentage value.

    I dati seguenti mostrano quattro intervalli di campionamento di due secondi, per uno studio di otto secondi.The following data shows four sampling intervals of two seconds, for an 8-second study. Le colonne Gen0, Gen1 e Gen2 mostrano il numero di operazioni di Garbage Collection eseguite durante l'intervallo per la generazione.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  
    

    Queste informazioni non indicano quando è avvenuta l'operazione di Garbage Collection, ma è possibile determinare il numero di operazioni di Garbage Collection eseguite in un intervallo di tempo specifico.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. Presupponendo il caso peggiore, la decima operazione di Garbage Collection di generazione 0 è terminata all'inizio del secondo intervallo, mentre l'undicesima è terminata alla fine del quinto intervallo.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. Poiché l'intervallo di tempo tra la fine della decima e la fine dell'undicesima operazione di Garbage Collection è circa 2 secondi e il contatore delle prestazioni indica 3%, la durata dell'undicesima operazione di Garbage Collection di generazione 0 è pari a (2 secondi * 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).

    Questo esempio include cinque periodi.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 seconda operazione di Garbage Collection di generazione 2 è iniziata durante il terzo intervallo ed è terminata durante il quinto intervallo.The second generation 2 garbage collection started during the third interval and finished at the fifth interval. Presupponendo il caso peggiore, l'ultima operazione di Garbage Collection è avvenuta per una raccolta di generazione 0 terminata all'inizio del secondo intervallo, mentre l'operazione di Garbage Collection di generazione 2 è terminata alla fine del quinto intervallo.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. Di conseguenza, l'intervallo di tempo tra la fine dell'operazione di Garbage Collection di generazione 0 e la fine dell'operazione di Garbage Collection di generazione 2 è 4 secondi.Therefore, the time between the end of the generation 0 garbage collection and the end of the generation 2 garbage collection is 4 seconds. Poiché il contatore % Time in GC indica 20%, la quantità massima di tempo che l'operazione di Garbage Collection di generazione 2 avrebbe potuto impiegare è (4 secondi * 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).

  • In alternativa, è possibile determinare la lunghezza di un'operazione di Garbage Collection usando gli eventi ETW di Garbage Collection e analizzando le informazioni per stabilire la durata dell'operazione di Garbage Collection.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.

    Ad esempio, i dati seguenti mostrano una sequenza di eventi verificatasi durante un'operazione di Garbage Collection non simultanea.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 sospensione del thread gestito ha richiesto 26 us (GCSuspendEEEnd - GCSuspendEEBegin_V1).Suspending the managed thread took 26us (GCSuspendEEEndGCSuspendEEBegin_V1).

    L'effettiva operazione di Garbage Collection ha richiesto 4,8 ms (GCEnd_V1 - GCStart_V1).The actual garbage collection took 4.8ms (GCEnd_V1GCStart_V1).

    La ripresa dei thread gestiti ha richiesto 21 us (GCRestartEEEnd - GCRestartEEBegin).Resuming the managed threads took 21us (GCRestartEEEndGCRestartEEBegin).

    L'output seguente offre un esempio di un'operazione di Garbage Collection in background e include il processo, il thread e i campi evento.The following output provides an example for background garbage collection, and includes the process, thread, and event fields. Non tutti i dati vengono visualizzati.(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          
    

    L'evento GCStart_V1 in corrispondenza di 42504816 indica che si tratta di un'operazione di Garbage Collection in background, perché l'ultimo campo è 1.The GCStart_V1 event at 42504816 indicates that this is a background garbage collection, because the last field is 1. Questa diventa l'operazione di Garbage Collection n.This becomes garbage collection No. 102019.102019.

    L'evento GCStart si verifica perché è necessaria un'operazione di Garbage Collection effimera prima di avviare un'operazione di Garbage Collection in background.The GCStart event occurs because there is a need for an ephemeral garbage collection before you start a background garbage collection. Questa diventa l'operazione di Garbage Collection n.This becomes garbage collection No. 102020.102020.

    In corrispondenza di 42514170, l'operazione di Garbage Collection n.At 42514170, garbage collection No. 102020 viene completata.102020 finishes. I thread gestiti vengono riavviati a questo punto.The managed threads are restarted at this point. Questa operazione viene completata nel thread 4372, che ha attivato l'operazione di Garbage Collection in background.This is completed on thread 4372, which triggered this background garbage collection.

    Nel thread 4744 si verifica una sospensione.On thread 4744, a suspension occurs. Si tratta dell'unica volta in cui l'operazione di Garbage Collection in background deve sospendere i thread gestiti.This is the only time at which the background garbage collection has to suspend managed threads. Questa durata è di circa 99 ms ((63784407-63685394)/1000).This duration is approximately 99ms ((63784407-63685394)/1000).

    L'evento GCEnd per l'attività di Garbage Collection in background si trova in corrispondenza di 89931423.The GCEnd event for the background garbage collection is at 89931423. Di conseguenza, l'operazione di Garbage Collection è durata circa 47 secondi ((89931423-42504816)/1000).This means that the background garbage collection lasted for about 47seconds ((89931423-42504816)/1000).

    Durante l'esecuzione dei thread gestiti, è possibile visualizzare un numero qualsiasi di operazioni di Garbage Collection effimere in esecuzione.While the managed threads are running, you can see any number of ephemeral garbage collections occurring.

Per determinare che cosa ha attivato un'operazione di Garbage CollectionTo determine what triggered a garbage collection
  • Nel debugger WinDbg o di Visual Studio con l'estensione del debugger SOS caricata, digitare il comando seguente per mostrare tutti i thread con i rispettivi stack di chiamate: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

    Questo comando genera un output simile al seguente.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  
    

    Se l'operazione di Garbage Collection è stata provocata da una notifica di memoria insufficiente dal sistema operativo, lo stack di chiamate è simile, ad eccezione del fatto che il thread è il thread del finalizzatore.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. Il thread del finalizzatore ottiene una notifica di memoria insufficiente asincrona e provoca l'operazione di Garbage Collection.The finalizer thread gets an asynchronous low memory notification and induces the garbage collection.

    Se l'operazione di Garbage Collection è stata causata dall'allocazione di memoria, lo stack viene visualizzato in questo modo: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 helper JIT (JIT_New*) chiama infine GCHeap::GarbageCollectGeneration.A just-in-time helper (JIT_New*) eventually calls GCHeap::GarbageCollectGeneration. Se si determina che le operazioni di Garbage Collection di generazione 2 sono causate da allocazioni, è necessario definire gli oggetti raccolti da tali operazioni e come evitarli.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. Ovvero, si vuole determinare la differenza tra l'inizio e la fine di un'operazione di Garbage Collection di generazione 2, nonché gli oggetti che hanno provocato la raccolta di generazione 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.

    Ad esempio, digitare il comando seguente nel debugger per mostrare l'inizio di una raccolta di generazione 2:For example, type the following command in the debugger to show the beginning of a generation 2 collection:

    !dumpheap –stat!dumpheap –stat

    Output di esempio (abbreviato per mostrare gli oggetti che usano la maggior parte dello spazio):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  
    

    Ripetere il comando alla fine della generazione 2:Repeat the command at the end of generation 2:

    !dumpheap –stat!dumpheap –stat

    Output di esempio (abbreviato per mostrare gli oggetti che usano la maggior parte dello spazio):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  
    

    Gli oggetti double[] sono scomparsi dalla fine dell'output, a indicare che sono stati raccolti.The double[] objects disappeared from the end of the output, which means that they were collected. Questi oggetti corrispondono a circa 70 MB.These objects account for approximately 70 MB. Gli oggetti rimanenti non sono cambiati molto.The remaining objects did not change much. Di conseguenza, questi oggetti double[] sono il motivo per cui si è verificata un'operazione di Garbage Collection di generazione 2 .Therefore, these double[] objects were the reason why this generation 2 garbage collection occurred. Il passaggio successivo consiste nel determinare il motivo per cui gli oggetti double[] sono ancora presenti e perché sono diventati inutilizzati.Your next step is to determine why the double[] objects are there and why they died. È possibile chiedere allo sviluppatore del codice da dove provengono questi oggetti oppure è possibile usare il comando gcroot.You can ask the code developer where these objects came from, or you can use the gcroot command.

Per determinare se l'utilizzo elevato della CPU è causato da Garbage CollectionTo determine whether high CPU usage is caused by garbage collection
  • Correlare il valore del contatore delle prestazioni della memoria % Time in GC alla durata del processo.Correlate the % Time in GC memory performance counter value with the process time.

    Se il valore % Time in GC mostra la presenza di picchi contemporaneamente alla durata del processo, l'operazione di Garbage Collection è la causa dell'elevato utilizzo della CPU.If the % Time in GC value spikes at the same time as process time, garbage collection is causing a high CPU usage. In caso contrario, profilare l'applicazione per individuare il punto in cui si verifica un utilizzo elevato.Otherwise, profile the application to find where the high usage is occurring.

Vedere ancheSee Also

Garbage CollectionGarbage Collection