Я записал эту небольшую тестовую программу:
using System;
namespace GCMemTest
{
class Program
{
static void Main(string[] args)
{
System.GC.Collect();
System.Diagnostics.Process pmCurrentProcess = System.Diagnostics.Process.GetCurrentProcess();
long startBytes = pmCurrentProcess.PrivateMemorySize64;
double kbStart = (double)(startBytes) / 1024.0;
System.Console.WriteLine("Currently using " + kbStart + "KB.");
{
int size = 2000000;
string[] strings = new string[size];
for(int i = 0; i < size; i++)
{
strings[i] = "blabla" + i;
}
}
System.GC.Collect();
pmCurrentProcess = System.Diagnostics.Process.GetCurrentProcess();
long endBytes = pmCurrentProcess.PrivateMemorySize64;
double kbEnd = (double)(endBytes) / 1024.0;
System.Console.WriteLine("Currently using " + kbEnd + "KB.");
System.Console.WriteLine("Leaked " + (kbEnd - kbStart) + "KB.");
System.Console.ReadKey();
}
}
}
Вывод в Сборке конечных версий:
Currently using 18800KB.
Currently using 118664KB.
Leaked 99864KB.
Я предполагаю, что вызов GC.collect удалит выделенные строки, так как они выходят из объема, но кажется, что он не делает. Я не понимаю, ни могу я находить объяснение его. Возможно, кто-либо здесь?
Спасибо, Alex
Действительно, я использовал частный размер памяти, потому что он наиболее близок к тому, что есть в Process Explorer
, если я перепишу программу с GC.GetTotalMemory вроде этого:
using System;
namespace GCMemTest
{
class Program
{
static void Main(string[] args)
{
System.GC.Collect();
long startBytes = System.GC.GetTotalMemory(true);
{
string[] strings = new string[2000000];
for (int i = 0; i < 2000000; i++)
{
strings[i] = "blabla" + i;
}
strings = null;
}
System.GC.Collect();
long endBytes = System.GC.GetTotalMemory(true);
double kbStart = (double)(startBytes) / 1024.0;
double kbEnd = (double)(endBytes) / 1024.0;
System.Console.WriteLine("Leaked " + (kbEnd - kbStart) + "KB.");
System.Console.ReadKey();
}
}
}
Тогда вывод будет:
Leaked 0KB.
Только когда у меня есть 'strings = null;' это так, удалите его, и у меня утечка 100 МБ. Это означает, что локальная область видимости в основной подпрограмме не вызывает освобождения массива. Если я перенесу эту часть в статический метод Test и вызову его вместо этого, у меня будет утечка нескольких байтов. Я предполагаю, что из этого я должен узнать, что локальные области игнорируются сборщиком мусора.
Вы смотрите на размер частной памяти - управляемая куча будет расширена для размещения строк, но она не вернет память операционной системе при сборке мусора. Вместо этого управляемая куча будет больше, но в ней будет много свободного места, поэтому, если вы создадите больше объектов, куча не будет расширяться.
Если вы хотите посмотреть на память , используемую в управляемой куче, посмотрите GC.GetTotalMemory
. Обратите внимание, что из-за сложности сборки мусора во всем этом есть определенная шероховатость.