GC.RegisterForFullGCNotification(Int32, Int32) Metoda
Definicja
Ważne
Niektóre informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany przed wydaniem. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Określa, że powiadomienie odzyskiwania pamięci powinno być zgłaszane, gdy warunki preferują pełne odzyskiwanie pamięci i po zakończeniu odzyskiwania pamięci.
public:
static void RegisterForFullGCNotification(int maxGenerationThreshold, int largeObjectHeapThreshold);
public static void RegisterForFullGCNotification (int maxGenerationThreshold, int largeObjectHeapThreshold);
[System.Security.SecurityCritical]
public static void RegisterForFullGCNotification (int maxGenerationThreshold, int largeObjectHeapThreshold);
static member RegisterForFullGCNotification : int * int -> unit
[<System.Security.SecurityCritical>]
static member RegisterForFullGCNotification : int * int -> unit
Public Shared Sub RegisterForFullGCNotification (maxGenerationThreshold As Integer, largeObjectHeapThreshold As Integer)
Parametry
- maxGenerationThreshold
- Int32
Liczba z zakresu od 1 do 99 określająca, kiedy powiadomienie powinno zostać podniesione na podstawie obiektów przydzielonych w generacji 2.
- largeObjectHeapThreshold
- Int32
Liczba z zakresu od 1 do 99 określająca, kiedy powiadomienie powinno zostać podniesione na podstawie obiektów przydzielonych w stercie dużych obiektów.
- Atrybuty
Wyjątki
maxGenerationThreshold
lub largeObjectHeapThreshold
nie ma zakresu od 1 do 99.
Ten element członkowski nie jest dostępny po włączeniu współbieżnego odzyskiwania pamięci. <Zobacz ustawienie środowiska uruchomieniowego gcConcurrent>, aby uzyskać informacje na temat wyłączania współbieżnego odzyskiwania pamięci.
Przykłady
W poniższym przykładzie pokazano, jak zarejestrować powiadomienie odzyskiwania pamięci i uruchomić wątek w celu monitorowania stanu powiadomienia odzyskiwania pamięci. Ten przykład kodu jest częścią większego przykładu dotyczącego tematu Powiadomienia odzyskiwania pamięci .
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Threading;
namespace GCNotify
{
ref class Program
{
private:
// Variable for continual checking in the
// While loop in the WaitForFullGCProc method.
static bool checkForNotify = false;
// Variable for suspending work
// (such servicing allocated server requests)
// after a notification is received and then
// resuming allocation after inducing a garbage collection.
static bool bAllocate = false;
// Variable for ending the example.
static bool finalExit = false;
// Collection for objects that
// simulate the server request workload.
static List<array<Byte>^>^ load = gcnew List<array<Byte>^>();
public:
static void Main()
{
try
{
// Register for a notification.
GC::RegisterForFullGCNotification(10, 10);
Console::WriteLine("Registered for GC notification.");
checkForNotify = true;
bAllocate = true;
// Start a thread using WaitForFullGCProc.
Thread^ thWaitForFullGC = gcnew Thread(gcnew ThreadStart(&WaitForFullGCProc));
thWaitForFullGC->Start();
// While the thread is checking for notifications in
// WaitForFullGCProc, create objects to simulate a server workload.
try
{
int lastCollCount = 0;
int newCollCount = 0;
while (true)
{
if (bAllocate)
{
load->Add(gcnew array<Byte>(1000));
newCollCount = GC::CollectionCount(2);
if (newCollCount != lastCollCount)
{
// Show collection count when it increases:
Console::WriteLine("Gen 2 collection count: {0}", GC::CollectionCount(2).ToString());
lastCollCount = newCollCount;
}
// For ending the example (arbitrary).
if (newCollCount == 500)
{
finalExit = true;
checkForNotify = false;
break;
}
}
}
}
catch (OutOfMemoryException^)
{
Console::WriteLine("Out of memory.");
}
finalExit = true;
checkForNotify = false;
GC::CancelFullGCNotification();
}
catch (InvalidOperationException^ invalidOp)
{
Console::WriteLine("GC Notifications are not supported while concurrent GC is enabled.\n"
+ invalidOp->Message);
}
}
public:
static void OnFullGCApproachNotify()
{
Console::WriteLine("Redirecting requests.");
// Method that tells the request queuing
// server to not direct requests to this server.
RedirectRequests();
// Method that provides time to
// finish processing pending requests.
FinishExistingRequests();
// This is a good time to induce a GC collection
// because the runtime will induce a full GC soon.
// To be very careful, you can check precede with a
// check of the GC.GCCollectionCount to make sure
// a full GC did not already occur since last notified.
GC::Collect();
Console::WriteLine("Induced a collection.");
}
public:
static void OnFullGCCompleteEndNotify()
{
// Method that informs the request queuing server
// that this server is ready to accept requests again.
AcceptRequests();
Console::WriteLine("Accepting requests again.");
}
public:
static void WaitForFullGCProc()
{
while (true)
{
// CheckForNotify is set to true and false in Main.
while (checkForNotify)
{
// Check for a notification of an approaching collection.
GCNotificationStatus s = GC::WaitForFullGCApproach();
if (s == GCNotificationStatus::Succeeded)
{
Console::WriteLine("GC Notifiction raised.");
OnFullGCApproachNotify();
}
else if (s == GCNotificationStatus::Canceled)
{
Console::WriteLine("GC Notification cancelled.");
break;
}
else
{
// This can occur if a timeout period
// is specified for WaitForFullGCApproach(Timeout)
// or WaitForFullGCComplete(Timeout)
// and the time out period has elapsed.
Console::WriteLine("GC Notification not applicable.");
break;
}
// Check for a notification of a completed collection.
s = GC::WaitForFullGCComplete();
if (s == GCNotificationStatus::Succeeded)
{
Console::WriteLine("GC Notification raised.");
OnFullGCCompleteEndNotify();
}
else if (s == GCNotificationStatus::Canceled)
{
Console::WriteLine("GC Notification cancelled.");
break;
}
else
{
// Could be a time out.
Console::WriteLine("GC Notification not applicable.");
break;
}
}
Thread::Sleep(500);
// FinalExit is set to true right before
// the main thread cancelled notification.
if (finalExit)
{
break;
}
}
}
private:
static void RedirectRequests()
{
// Code that sends requests
// to other servers.
// Suspend work.
bAllocate = false;
}
static void FinishExistingRequests()
{
// Code that waits a period of time
// for pending requests to finish.
// Clear the simulated workload.
load->Clear();
}
static void AcceptRequests()
{
// Code that resumes processing
// requests on this server.
// Resume work.
bAllocate = true;
}
};
}
int main()
{
GCNotify::Program::Main();
}
using System;
using System.Collections.Generic;
using System.Threading;
namespace GCNotify
{
class Program
{
// Variable for continual checking in the
// While loop in the WaitForFullGCProc method.
static bool checkForNotify = false;
// Variable for suspending work
// (such servicing allocated server requests)
// after a notification is received and then
// resuming allocation after inducing a garbage collection.
static bool bAllocate = false;
// Variable for ending the example.
static bool finalExit = false;
// Collection for objects that
// simulate the server request workload.
static List<byte[]> load = new List<byte[]>();
public static void Main(string[] args)
{
try
{
// Register for a notification.
GC.RegisterForFullGCNotification(10, 10);
Console.WriteLine("Registered for GC notification.");
checkForNotify = true;
bAllocate = true;
// Start a thread using WaitForFullGCProc.
Thread thWaitForFullGC = new Thread(new ThreadStart(WaitForFullGCProc));
thWaitForFullGC.Start();
// While the thread is checking for notifications in
// WaitForFullGCProc, create objects to simulate a server workload.
try
{
int lastCollCount = 0;
int newCollCount = 0;
while (true)
{
if (bAllocate)
{
load.Add(new byte[1000]);
newCollCount = GC.CollectionCount(2);
if (newCollCount != lastCollCount)
{
// Show collection count when it increases:
Console.WriteLine("Gen 2 collection count: {0}", GC.CollectionCount(2).ToString());
lastCollCount = newCollCount;
}
// For ending the example (arbitrary).
if (newCollCount == 500)
{
finalExit = true;
checkForNotify = false;
break;
}
}
}
}
catch (OutOfMemoryException)
{
Console.WriteLine("Out of memory.");
}
finalExit = true;
checkForNotify = false;
GC.CancelFullGCNotification();
}
catch (InvalidOperationException invalidOp)
{
Console.WriteLine("GC Notifications are not supported while concurrent GC is enabled.\n"
+ invalidOp.Message);
}
}
public static void OnFullGCApproachNotify()
{
Console.WriteLine("Redirecting requests.");
// Method that tells the request queuing
// server to not direct requests to this server.
RedirectRequests();
// Method that provides time to
// finish processing pending requests.
FinishExistingRequests();
// This is a good time to induce a GC collection
// because the runtime will induce a full GC soon.
// To be very careful, you can check precede with a
// check of the GC.GCCollectionCount to make sure
// a full GC did not already occur since last notified.
GC.Collect();
Console.WriteLine("Induced a collection.");
}
public static void OnFullGCCompleteEndNotify()
{
// Method that informs the request queuing server
// that this server is ready to accept requests again.
AcceptRequests();
Console.WriteLine("Accepting requests again.");
}
public static void WaitForFullGCProc()
{
while (true)
{
// CheckForNotify is set to true and false in Main.
while (checkForNotify)
{
// Check for a notification of an approaching collection.
GCNotificationStatus s = GC.WaitForFullGCApproach();
if (s == GCNotificationStatus.Succeeded)
{
Console.WriteLine("GC Notification raised.");
OnFullGCApproachNotify();
}
else if (s == GCNotificationStatus.Canceled)
{
Console.WriteLine("GC Notification cancelled.");
break;
}
else
{
// This can occur if a timeout period
// is specified for WaitForFullGCApproach(Timeout)
// or WaitForFullGCComplete(Timeout)
// and the time out period has elapsed.
Console.WriteLine("GC Notification not applicable.");
break;
}
// Check for a notification of a completed collection.
GCNotificationStatus status = GC.WaitForFullGCComplete();
if (status == GCNotificationStatus.Succeeded)
{
Console.WriteLine("GC Notification raised.");
OnFullGCCompleteEndNotify();
}
else if (status == GCNotificationStatus.Canceled)
{
Console.WriteLine("GC Notification cancelled.");
break;
}
else
{
// Could be a time out.
Console.WriteLine("GC Notification not applicable.");
break;
}
}
Thread.Sleep(500);
// FinalExit is set to true right before
// the main thread cancelled notification.
if (finalExit)
{
break;
}
}
}
private static void RedirectRequests()
{
// Code that sends requests
// to other servers.
// Suspend work.
bAllocate = false;
}
private static void FinishExistingRequests()
{
// Code that waits a period of time
// for pending requests to finish.
// Clear the simulated workload.
load.Clear();
}
private static void AcceptRequests()
{
// Code that resumes processing
// requests on this server.
// Resume work.
bAllocate = true;
}
}
}
open System
open System.Threading
// Variable for continual checking in the
// While loop in the WaitForFullGCProc method.
let mutable checkForNotify = false
// Variable for suspending work
// (such servicing allocated server requests)
// after a notification is received and then
// resuming allocation after inducing a garbage collection.
let mutable bAllocate = false
// Variable for ending the example.
let mutable finalExit = false
// Collection for objects that simulate the server request workload.
let load = ResizeArray<byte []>()
let redirectRequests () =
// Code that sends requests
// to other servers.
// Suspend work.
bAllocate <- false
let finishExistingRequests () =
// Code that waits a period of time
// for pending requests to finish.
// Clear the simulated workload.
load.Clear()
let acceptRequests () =
// Code that resumes processing
// requests on this server.
// Resume work.
bAllocate <- true
let onFullGCApproachNotify () =
printfn "Redirecting requests."
// Method that tells the request queuing
// server to not direct requests to this server.
redirectRequests ()
// Method that provides time to
// finish processing pending requests.
finishExistingRequests ()
// This is a good time to induce a GC collection
// because the runtime will induce a full GC soon.
// To be very careful, you can check precede with a
// check of the GC.GCCollectionCount to make sure
// a full GC did not already occur since last notified.
GC.Collect()
printfn "Induced a collection."
let onFullGCCompleteEndNotify () =
// Method that informs the request queuing server
// that this server is ready to accept requests again.
acceptRequests ()
printfn "Accepting requests again."
let waitForFullGCProc () =
let mutable broken = false
while not broken do
let mutable broken = false
// CheckForNotify is set to true and false in Main.
while checkForNotify && not broken do
// Check for a notification of an approaching collection.
match GC.WaitForFullGCApproach() with
| GCNotificationStatus.Succeeded ->
printfn "GC Notification raised."
onFullGCApproachNotify ()
// Check for a notification of a completed collection.
match GC.WaitForFullGCComplete() with
| GCNotificationStatus.Succeeded ->
printfn "GC Notification raised."
onFullGCCompleteEndNotify ()
| GCNotificationStatus.Canceled ->
printfn "GC Notification cancelled."
broken <- true
| _ ->
// Could be a time out.
printfn "GC Notification not applicable."
broken <- true
| GCNotificationStatus.Canceled ->
printfn "GC Notification cancelled."
broken <- true
| _ ->
// This can occur if a timeout period
// is specified for WaitForFullGCApproach(Timeout)
// or WaitForFullGCComplete(Timeout)
// and the time out period has elapsed.
printfn "GC Notification not applicable."
broken <- true
Thread.Sleep 500
// FinalExit is set to true right before
// the main thread cancelled notification.
if finalExit then broken <- true
try
// Register for a notification.
GC.RegisterForFullGCNotification(10, 10)
printfn "Registered for GC notification."
checkForNotify <- true
bAllocate <- true
// Start a thread using WaitForFullGCProc.
let thWaitForFullGC = Thread(ThreadStart waitForFullGCProc)
thWaitForFullGC.Start()
// While the thread is checking for notifications in
// WaitForFullGCProc, create objects to simulate a server workload.
try
let mutable lastCollCount = 0
let mutable newCollCount = 0
let mutable broken = false
while not broken do
if bAllocate then
load.Add(Array.zeroCreate<byte> 1000)
newCollCount <- GC.CollectionCount 2
if newCollCount <> lastCollCount then
// Show collection count when it increases:
printfn $"Gen 2 collection count: {GC.CollectionCount(2)}"
lastCollCount <- newCollCount
// For ending the example (arbitrary).
if newCollCount = 500 then
finalExit <- true
checkForNotify <- false
broken <- true
with :? OutOfMemoryException -> printfn "Out of memory."
finalExit <- true
checkForNotify <- false
GC.CancelFullGCNotification()
with :? InvalidOperationException as invalidOp ->
printfn $"GC Notifications are not supported while concurrent GC is enabled.\n{invalidOp.Message}"
Imports System.Collections.Generic
Imports System.Threading
Class Program
' Variables for continual checking in the
' While loop in the WaitForFullGcProc method.
Private Shared checkForNotify As Boolean = False
' Variable for suspending work
' (such as servicing allocated server requests)
' after a notification is received and then
' resuming allocation after inducing a garbage collection.
Private Shared bAllocate As Boolean = False
' Variable for ending the example.
Private Shared finalExit As Boolean = False
' Collection for objects that
' simulate the server request workload.
Private Shared load As New List(Of Byte())
Public Shared Sub Main(ByVal args() As String)
Try
' Register for a notification.
GC.RegisterForFullGCNotification(10, 10)
Console.WriteLine("Registered for GC notification.")
bAllocate = True
checkForNotify = True
' Start a thread using WaitForFullGCProc.
Dim thWaitForFullGC As Thread = _
New Thread(New ThreadStart(AddressOf WaitForFullGCProc))
thWaitForFullGC.Start()
' While the thread is checking for notifications in
' WaitForFullGCProc, create objects to simulate a server workload.
Try
Dim lastCollCount As Integer = 0
Dim newCollCount As Integer = 0
While (True)
If bAllocate = True Then
load.Add(New Byte(1000) {})
newCollCount = GC.CollectionCount(2)
If (newCollCount <> lastCollCount) Then
' Show collection count when it increases:
Console.WriteLine("Gen 2 collection count: {0}", _
GC.CollectionCount(2).ToString)
lastCollCount = newCollCount
End If
' For ending the example (arbitrary).
If newCollCount = 500 Then
finalExit = True
checkForNotify = False
bAllocate = False
Exit While
End If
End If
End While
Catch outofMem As OutOfMemoryException
Console.WriteLine("Out of memory.")
End Try
finalExit = True
checkForNotify = False
GC.CancelFullGCNotification()
Catch invalidOp As InvalidOperationException
Console.WriteLine("GC Notifications are not supported while concurrent GC is enabled." _
& vbLf & invalidOp.Message)
End Try
End Sub
Public Shared Sub OnFullGCApproachNotify()
Console.WriteLine("Redirecting requests.")
' Method that tells the request queuing
' server to not direct requests to this server.
RedirectRequests()
' Method that provides time to
' finish processing pending requests.
FinishExistingRequests()
' This is a good time to induce a GC collection
' because the runtime will induce a ful GC soon.
' To be very careful, you can check precede with a
' check of the GC.GCCollectionCount to make sure
' a full GC did not already occur since last notified.
GC.Collect()
Console.WriteLine("Induced a collection.")
End Sub
Public Shared Sub OnFullGCCompleteEndNotify()
' Method that informs the request queuing server
' that this server is ready to accept requests again.
AcceptRequests()
Console.WriteLine("Accepting requests again.")
End Sub
Public Shared Sub WaitForFullGCProc()
While True
' CheckForNotify is set to true and false in Main.
While checkForNotify
' Check for a notification of an approaching collection.
Dim s As GCNotificationStatus = GC.WaitForFullGCApproach
If (s = GCNotificationStatus.Succeeded) Then
Console.WriteLine("GC Notification raised.")
OnFullGCApproachNotify()
ElseIf (s = GCNotificationStatus.Canceled) Then
Console.WriteLine("GC Notification cancelled.")
Exit While
Else
' This can occur if a timeout period
' is specified for WaitForFullGCApproach(Timeout)
' or WaitForFullGCComplete(Timeout)
' and the time out period has elapsed.
Console.WriteLine("GC Notification not applicable.")
Exit While
End If
' Check for a notification of a completed collection.
s = GC.WaitForFullGCComplete
If (s = GCNotificationStatus.Succeeded) Then
Console.WriteLine("GC Notifiction raised.")
OnFullGCCompleteEndNotify()
ElseIf (s = GCNotificationStatus.Canceled) Then
Console.WriteLine("GC Notification cancelled.")
Exit While
Else
' Could be a time out.
Console.WriteLine("GC Notification not applicable.")
Exit While
End If
End While
Thread.Sleep(500)
' FinalExit is set to true right before
' the main thread cancelled notification.
If finalExit Then
Exit While
End If
End While
End Sub
Private Shared Sub RedirectRequests()
' Code that sends requests
' to other servers.
' Suspend work.
bAllocate = False
End Sub
Private Shared Sub FinishExistingRequests()
' Code that waits a period of time
' for pending requests to finish.
' Clear the simulated workload.
load.Clear()
End Sub
Private Shared Sub AcceptRequests()
' Code that resumes processing
' requests on this server.
' Resume work.
bAllocate = True
End Sub
End Class
Uwagi
Dla każdej generacji moduł odśmiecanie pamięci ustawia próg alokacji do tej generacji. Gdy rozmiar alokacji przekroczy ten próg, w tej generacji zostanie wyzwolone odzyskiwanie pamięci. Jeśli na przykład próg generacji 2 wynosi 20 MB (co oznacza, że 20 MB przetrwa kolekcje generacji 1 i jest promowane do generacji 2), a ponad 20 MB przetrwało generację 1 i zostanie wyświetlony monit o wygenerowanie 2. generacji, kolejna próba odzyskiwania pamięci zostanie podjęta jako kolekcja generacji 2. Podobnie, jeśli próg dużych stertów obiektów (LOH) wynosi 20 MB, a aplikacja przydzieliła ponad 20 MB dużych obiektów, kolejna próba odzyskiwania pamięci zostanie również podjęta jako kolekcja generacji 2 (ponieważ LOH jest zbierana tylko w przypadku odzyskiwania pamięci gen2).
Progi maxGenerationThreshold
i largeObjectHeapThreshold
kontrolują, ile wcześniej otrzymasz, zanim nastąpi pełne odzyskiwanie pamięci. Im większa wartość progowa, tym więcej alokacji może wystąpić między powiadomieniem a następnym pełnym odzyskiwaniem pamięci.
Jeśli masz sytuacje, w których pełne odzyskiwanie pamięci przez środowisko uruchomieniowe języka wspólnego będzie niekorzystnie wpływać na wydajność aplikacji, możesz poprosić o powiadomienie, gdy środowisko uruchomieniowe ma wykonać pełne odzyskiwanie pamięci i obejście tej kolekcji przez samodzielne utworzenie kolekcji (przy użyciu Collect metody), gdy warunki są nadal korzystne. Oprócz samodzielnego zmieniania harmonogramu odzyskiwania pamięci pełne powiadomienie GC jest przydatne w następujących scenariuszach:
Monitorujesz podejście do pełnego odzyskiwania pamięci, a po powiadomieniu o zbliżaniu się tego podejścia można zmniejszyć rozmiar danych na żywo (na przykład przez zwolnienie niektórych wpisów pamięci podręcznej). W związku z tym po zakończeniu odzyskiwania pamięci można odzyskać więcej pamięci.
Monitorujesz ukończenie pełnego odzyskiwania pamięci, aby można było zebrać pewne statystyki. Możesz na przykład zmierzyć rozmiar sterty po zakończeniu GC, aby znać rozmiar danych na żywo. (Po pełnym GC sterta jest w najmniejszym rozmiarze).
Aby uzyskać więcej informacji o tym, co reprezentuje pełne odzyskiwanie pamięci, zobacz Powiadomienia dotyczące odzyskiwania pamięci.
Po zarejestrowaniu się w celu uzyskania powiadomienia o odśmieceniu pamięci można otrzymywać powiadomienia o zbliżaniu się pełnego odzyskiwania pamięci i zakończeniu jego wykonywania. Ten wzorzec przypomina sposób, w jaki system operacyjny monitoruje powiadomienia o niskiej ilości pamięci.
Użyj następujących wskazówek dotyczących określania maxGenerationThreshold
parametrów i largeObjectHeapThreshold
:
Większa wartość progowa, tym więcej alokacji nastąpi między powiadomieniem a pełnym odzyskiwaniem pamięci.
Większa wartość progowa zapewnia więcej możliwości dla środowiska uruchomieniowego w celu sprawdzenia pod kątem zbliżającej się kolekcji. Zwiększa to prawdopodobieństwo powiadomienia. Nie należy jednak ustawiać zbyt wysokiego progu, ponieważ powoduje to zwiększenie alokacji przed wywołaniem następnej kolekcji przez środowisko uruchomieniowe.
Po wywołaniu kolekcji samodzielnie po powiadomieniu przy użyciu wartości progowej mniej obiektów zostanie odzyskanych niż zostanie odzyskanych przez następną kolekcję środowiska uruchomieniowego.
Mniejsza wartość progowa, tym mniejsza liczba alokacji między powiadomieniem a pełnym odzyskiwaniem pamięci.