При тестировании производительности приложений я столкнулся с довольно странным поведением GC.Короче говоря, GC запускается даже на пустой программе без выделения времени выполнения!
Следующее приложение демонстрирует проблему:
using System;
using System.Collections.Generic;
public class Program
{
// Preallocate strings to avoid runtime allocations.
static readonly List<string> Integers = new List<string>();
static int StartingCollections0, StartingCollections1, StartingCollections2;
static Program()
{
for (int i = 0; i < 1000000; i++)
Integers.Add(i.ToString());
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
static void Main(string[] args)
{
DateTime start = DateTime.Now;
int i = 0;
Console.WriteLine("Test 1");
StartingCollections0 = GC.CollectionCount(0);
StartingCollections1 = GC.CollectionCount(1);
StartingCollections2 = GC.CollectionCount(2);
while (true)
{
if (++i >= Integers.Count)
{
Console.WriteLine();
break;
}
// 1st test - no collections!
{
if (i % 50000 == 0)
{
PrintCollections();
Console.Write(" - ");
Console.WriteLine(Integers[i]);
//System.Threading.Thread.Sleep(100);
// or a busy wait (run in debug mode)
for (int j = 0; j < 50000000; j++)
{ }
}
}
}
i = 0;
Console.WriteLine("Test 2");
StartingCollections0 = GC.CollectionCount(0);
StartingCollections1 = GC.CollectionCount(1);
StartingCollections2 = GC.CollectionCount(2);
while (true)
{
if (++i >= Integers.Count)
{
Console.WriteLine("Press any key to continue...");
Console.ReadKey(true);
return;
}
DateTime now = DateTime.Now;
TimeSpan span = now.Subtract(start);
double seconds = span.TotalSeconds;
// 2nd test - several collections
if (seconds >= 0.1)
{
PrintCollections();
Console.Write(" - ");
Console.WriteLine(Integers[i]);
start = now;
}
}
}
static void PrintCollections()
{
Console.Write(Integers[GC.CollectionCount(0) - StartingCollections0]);
Console.Write("|");
Console.Write(Integers[GC.CollectionCount(1) - StartingCollections1]);
Console.Write("|");
Console.Write(Integers[GC.CollectionCount(2) - StartingCollections2]);
}
}
Может кто-нибудь объяснить, что здесь происходит?У меня сложилось впечатление, что ГХ не запустится, если давление памяти не достигнет определенных пределов.Тем не менее, кажется, что он запускается (и собирает) все время - это нормально?
Редактировать: Я изменил программу, чтобы избежать всех распределений времени выполнения.
Редактировать 2: Хорошо, новая итерацияи кажется, что DateTime является виновником.Один из методов DateTime выделяет память (возможно, Subtract), что приводит к запуску GC.Первый тест теперь вызывает абсолютно нет коллекций - как и ожидалось - в то время как второй вызывает несколько.
Короче говоря, сборщик мусора запускается только тогда, когда он должен работать - я просто невольно генерировал давление памяти(DateTime - это структура, и я подумал, что она не будет генерировать мусор).