Почему выделено больше памяти, чем ожидалось? - PullRequest
4 голосов
/ 16 февраля 2020

Я играю с BenchmarkDo tNet и его функцией MemoryDiagnoser.

Учитывая следующий тест:

[Benchmark]
public void Dummy()
{
   var buffer = new byte[1];
}

Я ожидаю, что он выделит ровно 1 байт.

Но результат теста показывает, что было выделено 32 байта. Как так? Я нахожу это довольно вводящим в заблуждение.

| Method |     Mean |     Error |    StdDev |   Median | Ratio | Rank |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|------- |---------:|----------:|----------:|---------:|------:|-----:|-------:|------:|------:|----------:|
|  Dummy | 4.486 ns | 0.1762 ns | 0.5196 ns | 4.650 ns |  1.00 |    1 | 0.0038 |     - |     - |      32 B |

                                                                                      why not 1 byte? ^^^^

Ответы [ 3 ]

2 голосов
/ 18 февраля 2020

Я автор MemoryDiagnoser, и я описал, как читать результаты моего блога: https://adamsitnik.com/the-new-Memory-Diagnoser/#how-to-read-the-results

CLR делает какое-то выравнивание. Если вы попытаетесь выделить новый массив byte [1], он выделит массив byte [8].

Нам потребуется дополнительное место для заголовка объекта, указателя таблицы методов и длины массива. Накладные расходы в 3 раза больше размера указателя. 8 + 3x4 = 20 для 32-разрядных и 8 + 3x8 = 32 для 64-разрядных.

0 голосов
/ 18 февраля 2020

Вы не выделяете байт. Вы выделяете байтовый массив. Массив является ссылочным типом, и все экземпляры ссылочного типа поставляются с битом overhead . Таким образом, общий размер любого массива больше, чем размер элементов. Ответ Адама имеет хороший разбивку деталей.

0 голосов
/ 16 февраля 2020

Я подозреваю, что вы находитесь на «/ platform: x64». Массив байтов будет занимать пространство «24 байта + длина», так как каждый из его элементов имеет байты. Более того, на x64 все размеры округлены до ближайших 8 байтов.

Вот как вы можете измерить размер.

private void TestMemory(){
    long before = GC.GetTotalMemory(true);
    // Allocation code
    long after = GC.GetTotalMemory(true);
    double diff = after – before;
    Console.WriteLine(“Per object: “ + diff / size);
    // Stop the GC from messing up our measurements
    GC.KeepAlive(array);
}

Что касается вашего вопроса, why? Как упомянуто в комментариях, это детали реализации этого языка высокого уровня.

※ Из-за выравнивания памяти ← Как упоминалось в моем ответе

※ Также массивы включают некоторые метаданные, например их размер, чтобы вы не индексировали в случайную память. ← Это может быть связано с первой звездой

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...