Был ли опыт оптимизации, связанной с value type и reference type в C#?
Что проверяют
Есть ли у вас практика работы с памятью в .NET, а не заученное «структуры на стеке, классы в куче». Следом обычно просят рассказать, как вы измеряли эффект и где структура сделала только хуже.
Как отвечать
Ответ строится на своём случае: что тормозило, чем измеряли, что поменяли, какой получили результат. Цифры должны быть вашими, из профилировщика или бенчмарка: придуманные проценты рассыпаются на первом уточняющем вопросе.
Опорные точки, на которые обычно ложится реальный опыт:
- лишние аллокации: мелкие короткоживущие объекты в горячем цикле нагружают GC. Замена на
structилиreadonly structубирает аллокации в куче, если структура маленькая (ориентир Microsoft: до 16 байт) и неизменяемая; - боксинг: структура, приведённая к
objectили интерфейсу, упаковывается в кучу. Типичные места: необобщённые коллекции,string.Formatс value-аргументами, структура в роли ключаDictionaryбезIEquatable<T>; - копирование: большая структура копируется при каждой передаче. Помогают
inиref, но вызов метода у не-readonly структуры черезinсоздаёт защитную копию; - буферы:
Span<T>,stackallocиArrayPool<T>.Sharedдают работу с массивами и строками без новых аллокаций, аValueTaskэкономит аллокацию, когда асинхронный метод обычно завершается синхронно.
Измеряют это BenchmarkDotNet с [MemoryDiagnoser], счётчиками dotnet-counters (частота сборок, размер кучи) и снимками памяти в dotMemory или PerfView.
Если такой оптимизации не было, так и скажите, а затем разберите, как подошли бы: сначала профилирование, потом гипотеза, потом бенчмарк до и после. Честный разбор подхода ценится выше выдуманной истории.
Где спотыкаются
Говорят «структуры всегда живут на стеке». Структура в поле класса, в массиве или в захваченной замыканием переменной лежит в куче вместе с владельцем.
Переводят всё подряд в struct. Большие изменяемые структуры дорого копируются, теряют изменения при правке копии и в итоге работают медленнее классов.
Забывают про IEquatable<T> и GetHashCode. Стандартный ValueType.Equals может уходить в рефлексию и боксинг, и выигрыш от структуры исчезает на сравнениях.