TGViewer
C# Short Posts 🔞 C# Short Posts 🔞 @dimasshortposts · 306 subscribers
Post #269 425
🎱Прыгни с разбега в ObjectPool!

Не так давно прочитал книгу ✅ Высокопроизводительный код на .Net. И теперь осознал, что память не бесконечная и тратится очень быстро с каждым вызовом new. В мученических своих поисках о том как этого всего избегать, наткнулся на прикольный класс ObjectPool.

Идея простая:

1️⃣ Создаете сколько-то пустых объектов в памяти заранее

2️⃣ Потом достаете их, заполняетете нужными данными, юзаете это дельце как не в себя

3️⃣ А в конце просто сбрасываете состояние этого объекта к нулю и потом переиспользуете, если нужно.

Долго думал, как же эту крутотень использовать. И что-то никак не мог найти практического применения. А потом чет поскреб по сусекам и осознал, что в кэшах же!

Для примера. Есть самый простой в реализации кэш со словарем в качестве хранилища:


public class ExpensiveObject
{
public int Data { get; set; }

public ExpensiveObject()
{
Data = new Random().Next();
}
}

public class SimpleCache
{
private readonly Dictionary<string, ExpensiveObject> _cache = new Dictionary<string, ExpensiveObject>();

public ExpensiveObject Get(string key)
{
if (!_cache.TryGetValue(key, out var obj))
{
// Если объекта по ключу нет, создаём новый
obj = new ExpensiveObject();
_cache[key] = obj;
}
return obj;
}
}


В чем минус этого кэша. Каждый раз, когда вы добавляете в него новое значение, вы кладете объект в кучу. В этой реализации нет очистки кэша, и это, конечно, может плохо кончиться. Но, даже если добавить очистку, вы все равно будете через какое-то время триггерить сборку мусора, что тоже не очень хорошо.

Поэтому на первый план выходит идея – а что если заранее создать кучу пустых объектов и по очереди их заполнять нужными данными на время использования. Делаем то же самое на ObjectPool.

Сначала добавим немного сервисных штук:


using Microsoft.Extensions.ObjectPool;

public class ExpensiveObject
{
public int Data { get; set; }

public ExpensiveObject()
{
Data = new Random().Next();
}

// Добавляем метод сброса состояния для нашего класса
public void Reset()
{
Data = 0;
}
}

// Создаем политику работы с БАССЕЙНОМ для нашего объекта
public class ExpensiveObjectPooledPolicy : PooledObjectPolicy<ExpensiveObject>
{
// то бишь говорим, как создать
public override ExpensiveObject Create() => new ExpensiveObject();

// и как очистить состояние, после того как поюзали
public override bool Return(ExpensiveObject obj)
{
obj.Reset();
return true;
}
}


В этой части главное – не забыть модифицировать метод Return(ExpensiveObject obj), если добавили новое поле.

Если все сделали, то потом используем в пулле


using Microsoft.Extensions.ObjectPool;

public class OptimizedCache
{
private readonly ObjectPool<ExpensiveObject> _objectPool;
private readonly Dictionary<string, ExpensiveObject> _cache = new Dictionary<string, ExpensiveObject>();

public OptimizedCache(int maximumRetained = 20)
{
var policy = new ExpensiveObjectPooledPolicy();
_objectPool = new DefaultObjectPool<ExpensiveObject>(policy, maximumRetained);
}

public ExpensiveObject Get(string key)
{
if (!_cache.TryGetValue(key, out var obj))
{
obj = _objectPool.Get();
_cache[key] = obj;
}
return obj;
}

// Когда поюзали объект, можем его удалить.
public void Remove(string key)
{
if (_cache.TryGetValue(key, out var obj))
{
_cache.Remove(key);
_objectPool.Return(obj);
}
}
}



Если что, это непотокобезопасная реализация, разумеется, и тут разумеется не поможет конкаррент дикшенари и вот это все. То есть нужно будет чутка заморочиться с синхронизацией. Если кто-то юзает объект прямо сейчас, то нужно это отслеживать и дать чуваку доделать делишки и дождаться пока объект вернется в пул в первозданном виде.

Придется чутка подзаморочитсья. Но идею думаю вы уловили.
  • ❤‍🔥 1
  • 🔥 1
More from @dimasshortposts
  1. Sep 26, 2026🧵 Тредик для вопросов по докладу про MAF на дотнексте В докладе многие подробности опусти…
  2. Sep 23, 2026Даже самым хардкорным ребятам надо отдыхать, так что отдыхаем, мои чюваки 🕺 🧑‍💻dp🥁 #he…
  3. Sep 16, 2026🎯 Instrumented Tier0: профилирование кода В прошлый раз мы разобрали два уровня компиляци…
  4. Sep 15, 2026🔜 Готовлюсь к DOTNEXT 2026 В прошлом году за две недели до выступления я зачитывал свой д…
  5. Sep 9, 2026C# Short Posts 🔞 pinned «🐸 О чём этот канал? Кажется, я уже достаточно давно веду этот к…
  6. Sep 9, 2026🐸 О чём этот канал? Кажется, я уже достаточно давно веду этот канальчик, и пора бы описат…
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 →