строковое интернирование c#

Я пытаюсь понять строковое интернирование и почему, кажется, не работает в моем примере. Точка примера должна показать Примеру 1 использование меньше (намного меньше памяти), поскольку это должно только иметь 10 строк в памяти. Однако в коде и ниже примера используют примерно тот же объем памяти (виртуальный размер и ниже рабочий набор).

Совет, почему пример 1 не использует намного меньше памяти?Спасибо

Пример 1:

        IList<string> list = new List<string>(10000);

        for (int i = 0; i < 10000; i++)
        {
            for (int k = 0; k < 10; k++)
            {
                list.Add(string.Intern(k.ToString()));
            }

        }

        Console.WriteLine("intern Done");
        Console.ReadLine();

Пример 2:

        IList<string> list = new List<string>(10000);

        for (int i = 0; i < 10000; i++)
        {
            for (int k = 0; k < 10; k++)
            {
                list.Add(k.ToString());
            }

        }

        Console.WriteLine("intern Done");
        Console.ReadLine();
11
задан CodingThunder 24 March 2010 в 10:10
поделиться

3 ответа

Из msdn Во-вторых, чтобы интернировать строку, вы должны сначала создать строку. Память, используемая объектом String, по-прежнему должна быть выделена, даже если память в конечном итоге будет удалена сборщиком мусора.

2
ответ дан 3 December 2019 в 03:51
поделиться

Проблема в том, что ToString() все равно выделит новую строку, а затем интернирует ее. Если сборщик мусора не запускается для сбора этих "временных" строк, то использование памяти будет таким же.

Кроме того, длина ваших строк довольно мала. 10 000 строк, длина которых в основном составляет всего один символ, - это разница в памяти примерно в 20 КБ, которую вы, скорее всего, не заметите. Попробуйте использовать более длинные строки (или гораздо больше их) и выполнить сборку мусора перед проверкой использования памяти.

Вот пример, который действительно показывает разницу:

class Program
{
    static void Main(string[] args)
    {
        int n = 100000;

        if (args[0] == "1")
            WithIntern(n);
        else
            WithoutIntern(n);
    }

    static void WithIntern(int n)
    {
        var list = new List<string>(n);

        for (int i = 0; i < n; i++)
        {
            for (int k = 0; k < 10; k++)
            {
                list.Add(string.Intern(new string('x', k * 1000)));
            }
        }

        GC.Collect();
        Console.WriteLine("Done.");
        Console.ReadLine();
    }

    static void WithoutIntern(int n)
    {
        var list = new List<string>(n);

        for (int i = 0; i < n; i++)
        {
            for (int k = 0; k < 10; k++)
            {
                list.Add(new string('x', k * 1000));
            }
        }

        GC.Collect();
        Console.WriteLine("Done.");
        Console.ReadLine();
    }
}
17
ответ дан 3 December 2019 в 03:51
поделиться

Помните, что CLR управляет памятью от имени вашего процесса, поэтому очень трудно определить объем управляемой памяти, глядя на виртуальный размер и рабочий набор. CLR обычно выделяет и освобождает память кусками. Их размер варьируется в зависимости от деталей реализации, но из-за этого практически невозможно измерить использование управляемой кучи на основе счетчиков памяти процесса.

Однако, если вы посмотрите на фактическое использование памяти в примерах, вы увидите разницу.

Пример 1

0:005>!dumpheap -stat
...
00b6911c      137         4500 System.String
0016be60        8       480188      Free
00b684c4       14       649184 System.Object[]
Total 316 objects
0:005> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x01592dcc
generation 1 starts at 0x01592dc0
generation 2 starts at 0x01591000
ephemeral segment allocation context: none
 segment    begin allocated     size
01590000 01591000  01594dd8 0x00003dd8(15832)
Large object heap starts at 0x02591000
 segment    begin allocated     size
02590000 02591000  026a49a0 0x001139a0(1128864)
Total Size  0x117778(1144696)
------------------------------
GC Heap Size  0x117778(1144696)

Пример 2

0:006> !dumpheap -stat
...
00b684c4       14       649184 System.Object[]
00b6911c   100137      2004500 System.String
Total 100350 objects
0:006> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x0179967c
generation 1 starts at 0x01791038
generation 2 starts at 0x01591000
ephemeral segment allocation context: none
 segment    begin allocated     size
01590000 01591000  0179b688 0x0020a688(2139784)
Large object heap starts at 0x02591000
 segment    begin allocated     size
02590000 02591000  026a49a0 0x001139a0(1128864)
Total Size  0x31e028(3268648)
------------------------------
GC Heap Size  0x31e028(3268648)

Как видно из приведенных результатов, второй пример действительно использует больше памяти на управляемой куче.

7
ответ дан 3 December 2019 в 03:51
поделиться
Другие вопросы по тегам:

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