TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.74K subscribers
Post #2929 2.57K
День 2432. #ЗаметкиНаПолях
Экономим Память, Как Профессионалы. 5 Продвинутых Техник. Окончание

Начало

3. GC.AllocateUninitializedArray<T> для более быстрой работы с массивами
При создании нового массива в .NET среда выполнения обнуляет его. Обычно это хорошо, предсказуемое поведение, никаких мусорных данных. Но что, если вам не нужно изначальное содержимое, ведь вы всё равно перезапишете каждый элемент? Обнуление — пустая трата времени.
Стандартный способ:
// Автоматически обнуляется
int[] arr = new int[1000];
for (int i = 0; i < arr.Length; i++)
arr[i] = i; // Перезаписываем всё


Способ лучше:
int[] arr = GC.AllocateUninitializedArray<int>(1000);
for (int i = 0; i < arr.Length; i++)
arr[i] = i;

Почему: здесь среда выполнения пропускает очистку памяти. Это ускоряет выделение памяти, особенно для больших массивов.
Когда использовать: требуется дисциплина. Если вы читаете массив перед записью, вы получите мусорные значения. Но в таких сценариях, как сериализация, повторное использование буфера или краткие циклы с вычислениями, это может сэкономить время.
Выигрыш: ~15% для 1000 элементов.

4. ArrayPool<T>.Shared и IMemoryOwner
Если вы многократно выделяете большие массивы в цикле, сборщик мусора вас возненавидит. Именно здесь на помощь приходит ArrayPool<T> — общий пул массивов, который можно арендовать и вернуть.
Стандартный способ:
for (int i = 0; i < 1000; i++)
{
// аллокации каждый раз
var buffer = new byte[1024];
DoSomething(buffer);
}

Это приведёт к тысяче аллокаций, которые захламят кучу.

Способ лучше:
using System.Buffers;

for (int i = 0; i < 1000; i++)
{
using IMemoryOwner<byte> owner =
MemoryPool<byte>.Shared.Rent(1024);
var memory = owner.Memory;
DoSomething(memory.Span);
}

Почему: мы арендуем буфер из пула, используем его и возвращаем при уничтожении IMemoryOwner<T>. Никакие выделения памяти не перегружают сборщик мусора.
Когда использовать: особенно актуально в сценариях с высокой пропускной способностью, таких как сетевые серверы, конвейеры или обработка видео. Кроме того, это безопаснее, чем просто арендовать и возвращать массивы, поскольку IMemoryOwner<T> гарантирует корректную очистку.
Выигрыш: более чем в 2 раза быстрее и 1 аллокация вместо 1000.

5. ObjectPool<T> для дорогостоящих объектов
Создание некоторых объектов требует больших затрат. Если вы постоянно создаёте и уничтожаете их, вы тратите не только память, но и ресурсы процессора. Поможет ObjectPool<T>.
Без пулинга:
for (int i = 0; i < 100; i++)
{
var sb = new StringBuilder(1024);
sb.Append("Hello ").Append(i);
Console.WriteLine(sb.ToString());
}

Это создаст 100 экземпляров StringBuilder. Они будут собраны GC, но зачем создавать столько?

Пулинг:
using Microsoft.Extensions.ObjectPool;
var provider = new DefaultObjectPoolProvider();
var pool = provider.CreateStringBuilderPool();

for (int i = 0; i < 100; i++)
{
var sb = pool.Get();
sb.Clear();
sb.Append("Hello ").Append(i);
Console.WriteLine(sb.ToString());
pool.Return(sb);
}

Почему: мы переиспользуем небольшой пул объектов StringBuilder. Выделение памяти значительно сокращается, и мы избегаем постоянного обращения к GC.
Когда использовать: фреймворки логирования, библиотеки сериализации или любые другие рабочие нагрузки, требующие создания множества временных объектов.
Выигрыш: примерно в 4 раза быстрее и в 50 раз меньше по памяти.

Итого
Если вы когда-нибудь заглядывали в свой профилировщик и задавались вопросом, почему так много времени тратится на сборку мусора или копирование памяти, эти приёмы помогут вам это исправить. Они подходят не для всех ситуаций, но, когда вы гонитесь за реальной производительностью, именно эти инструменты отличают «неплохое» приложение от действительно эффективного.

Источник: https://blog.stackademic.com/stop-wasting-memory-5-advanced-net-tricks-nobody-teaches-you-47376c1339e7
  • 👍 49
More from @netdeveloperdiary
  1. Sep 24, 2026День 2794. #Оффтоп #Здоровье Сегодня будет необычный пост. Завтра в Москве стартует конфер…
  2. Sep 23, 2026День 2793. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
  3. Sep 22, 2026День 2792. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
  4. Sep 21, 2026🔍Тестовое собеседование с Senior C# разработчиком уже завтра 22 сентября(уже завтра!) в 1…
  5. Sep 21, 2026День 2791. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
  6. Sep 20, 2026Post #3339
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →