Затраты на кучи в Java и .NET - PullRequest
       19

Затраты на кучи в Java и .NET

3 голосов
/ 06 февраля 2009

Я понимаю, как работает куча и сборщик мусора: сборка мусора происходит в течение нескольких поколений, выделение памяти происходит последовательно, во время сбора мусора свободное / неиспользуемое пространство сжимается при перемещении данных и формировании блока продолжения и т. Д.

Существуют ли какие-либо заголовки для выделенных блоков памяти и насколько они велики (я слышал, что это 8-16 байт для .NET CLR), и если присутствует выравнивание байтов, слов или четырех слов? Меня интересует любая информация для реализации JIT (Java) и CLR (.NET Framework или Mono) для процессорных архитектур x86 и x64.

Ответы [ 3 ]

5 голосов
/ 06 февраля 2009

Я считаю, что размер заголовка составляет два слова - одно для ссылки на тип, одно для блока синхронизации и другие флаги. Заполнения (я полагаю) достаточно, чтобы округлить общий размер до целого числа слов.

Например, ссылочный тип, содержащий только int, занимает 12 байтов на x86, как показано здесь:

using System;

public class Foo
{
    int x;

    public Foo(int x)
    {
        this.x = x;
    }
}

public class Test
{
    static void Main(string[] args)
    {
        int length = int.Parse(args[0]);

        Foo x = new Foo(0);
        Foo[] array = new Foo[length];
        // Make sure that JITting the string constructor doesn't
        // change things
        long start = GC.GetTotalMemory(true);
        for (int i=0; i < length; i++)
        {
            array[i] = new Foo(i);
        }
        long end = GC.GetTotalMemory(true);

        GC.KeepAlive(array);
        GC.KeepAlive(x);

        decimal totalDecimal = end-start;
        Console.WriteLine(totalDecimal / length);
    }
}

Один интересный момент - по какой-то причине экземпляр System.Object занимает 12 байтов (на x86) вместо 8, которые я бы иначе предсказал. Как будто минимальный размер составляет 12 байтов, но вы получаете первые четыре байта реальных данных бесплатно:)

Не знаю, почему указанный размер не является целым числом, кстати - я подозреваю, что это связано с небольшим количеством дополнительной памяти, необходимой для каждой страницы в управляемой куче, или с чем-то вроде этого. Иногда результат чуть больше 12, иногда чуть меньше 12 - это, кажется, зависит от указанной длины. (В предыдущей версии этого ответа была ошибка, при которой он анализировал первую аргумент командной строки arg, но затем игнорировал ее. Я исправил это.) В любом случае, я не верю, что эта небольшая неточность имеет какое-либо отношение к размеру отдельного объекта в памяти.

1 голос
/ 25 августа 2010

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

Существует несколько простых утилит, которые можно использовать для оценки накладных расходов для конкретного объекта, но нет ничего надежного (посмотрите, например, http://java.sun.com/docs/books/performance/1st_edition/html/JPRAMFootprint.fm.html).

В Java также есть интерфейс, который может дать вам размер объекта, включая накладные расходы, см. http://download -llnw.oracle.com / javase / 6 / docs / platform / jvmti / jvmti.html # GetObjectSize .

0 голосов
/ 06 февраля 2009

Я не знаю о Java, но для CLR выделено 1 собственное служебное слово на каждый выделенный тип reference . В 32-битных системах это будет 4 байта, а в 64-битных - 8 байтов.

...