#.net #string #memory #.net-4.0
#.net #строка #память #.net-4.0
Вопрос:
Я пытался выяснить накладные расходы на строку в .NET 4 x64. Это то, что у меня есть до сих пор.
- 16-байтовый заголовок объекта для x64
- 4 байта для поля StringLength (arrayLength отсутствует в .NET 4)
- (длина 1) * 2 байта для содержимого строки (UTF-16, завершается нулем)
Таким образом, вы ожидаете, что строка из 1 символа будет 16 4 4 = 24 байта. Она делится на 8, поэтому ей не нужно никаких дополнений.
Но когда я смотрю на размеры в WinDbg, я вижу, что они занимают 32 байта. Когда я !dumpobject
их называю, они говорят, что их размер составляет 28 байт, что, как я полагаю, округляется до 32. Что происходит? Происходит ли еще один раунд выравнивания памяти?
Комментарии:
1. Попробуйте сделать строку длиннее… Сколько памяти для 2, 3 и 4 символов?
2. @xanatos: 2 байта дополнительно на символ.
3. Начальный символ может быть выровнен?
4. @leppie Итак, 28 = 1 символ, 30 = 2 символа, 32 = 3 символа и 34 = 4 символа?
5. @xanatos: Прочитайте вопрос еще раз. 1 символ равен 32
![]()
Ответ №1:
Я подозреваю, что первый символ выровнен по 8-байтовой границе в x64, так что при передаче в качестве указателя на неуправляемый код это правильно выровненный указатель. Ваши цифры, безусловно, соответствуют тем, которые я недавно получил, измеряя размер строки, что привело к формулам:
32 bit: 14 length * 2 (rounded up to 4 bytes)
64 bit: 26 length * 2 (rounded up to 8 bytes)
Итак, в 64-разрядной среде CLR даже строка длиной 0, по моим подсчетам, занимает 32 байта.
Комментарии:
1. Кажется вероятным, что это 8-байтовое выравнивание по первому символу плюс 8-байтовое заполнение объекта в целом. Я полагаю, что следующий вопрос будет заключаться в том, какие поля будут выровнены таким образом. Я покопался, и это, похоже, не является общим правилом: например, когда вы смешиваете длинные и целые числа в классе, они с удовольствием плотно упаковываются вместе и не выравниваются по 8-байтовым границам. Поиск в Интернете ничего не дал.
![]()
2. Строки копируются с использованием целых чисел собственного размера, поэтому я полагаю, что они выровнены хотя бы частично, чтобы их можно было копировать более эффективно.
Ответ №2:
Округление до границ абзаца (16 байт) для оптимизации заполнения строки кэша на процессорах Intel?
Комментарии:
1. Я не думаю, что это так, потому что я также вижу кучу 40-байтовых строк в WinDbg.
Ответ №3:
Из того, что я понимаю, вы не можете полагаться ни на что на стороне реализации с .NET — только потому, что это x байт на вашем компьютере, это не значит, что это x байт на какой-то другой машине / версии .NET. т. Е. Опасно делать что-либо в коде, зная внутреннюю структуру структуры .NETклассы.
Комментарии:
1. Верно, но этот конкретный вопрос, похоже, вызван простым любопытством.