Использование памяти строк (или любые другие объекты) в .NET

Я записал эту небольшую тестовую программу:

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

6
задан ava 11 June 2010 в 09:37
поделиться

2 ответа

Действительно, я использовал частный размер памяти, потому что он наиболее близок к тому, что есть в 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 и вызову его вместо этого, у меня будет утечка нескольких байтов. Я предполагаю, что из этого я должен узнать, что локальные области игнорируются сборщиком мусора.

0
ответ дан 10 December 2019 в 02:42
поделиться

Вы смотрите на размер частной памяти - управляемая куча будет расширена для размещения строк, но она не вернет память операционной системе при сборке мусора. Вместо этого управляемая куча будет больше, но в ней будет много свободного места, поэтому, если вы создадите больше объектов, куча не будет расширяться.

Если вы хотите посмотреть на память , используемую в управляемой куче, посмотрите GC.GetTotalMemory . Обратите внимание, что из-за сложности сборки мусора во всем этом есть определенная шероховатость.

9
ответ дан 10 December 2019 в 02:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: