Какую самую интересную задачу делал за последний год?

Ответ

Самой интересной задачей была оптимизация критического API эндпоинта для массовой обработки данных, время отклика которого под нагрузкой выросло с ~200 мс до более 2 секунд. Проблема была неочевидной, так как на низкой нагрузке все работало хорошо.

Что было сделано:

  1. Профилирование: С помощью Application Insights и профилировщика памяти выявили проблему N+1 запросов к базе данных внутри цикла обработки коллекции, а также неоптимальную сериализацию крупных JSON-объектов.
  2. Оптимизация доступа к данным: Переписал логику, заменив цикл с отдельными вызовами на один запрос с использованием IN и последующее маппинговое соединение (lookup join) в памяти.
    
    // Было (упрощенно):
    foreach (var item in items)
    {
    var details = await _dbContext.Details.FirstOrDefaultAsync(d => d.ItemId == item.Id);
    // ... обработка
    }

// Стало: var itemIds = items.Select(i => i.Id).ToList(); var allDetails = await _dbContext.Details .Where(d => itemIds.Contains(d.ItemId)) .ToDictionaryAsync(d => d.ItemId);

foreach (var item in items) { if (allDetails.TryGetValue(item.Id, out var details)) { // ... обработка } }


3.  **Оптимизация сериализации:** Заменил рефлексивную сериализацию по умолчанию на сгенерированный с помощью Source Generators сериализатор System.Text.Json, что резко сократило аллокации памяти.
4.  **Кэширование:** Добавил двухуровневое кэширование (in-memory + распределенный Redis) для редко меняющихся справочных данных, которые участвовали в расчетах.

**Результат:** Время отклика API сократилось до ~50 мс (в 40 раз), потребление CPU упало на 70%, а количество обращений к БД уменьшилось на порядок. Задача была интересна сочетанием глубокого анализа, применения различных техник оптимизации и измеримым, значимым результатом для бизнеса.

Ответ 18+ 🔞

Да ты послушай, какая история приключилась! Сижу я значит, пью кофе, и тут прилетает алерт — наш главный API, который данные массово обрабатывает, сдулся конкретно. Под нагрузкой вместо положенных двухсот миллисекунд стал отвечать по две секунды, а то и больше. А на тестах-то всё летало, сука! Ну, думаю, ёпта, щас будем разбираться, где тут собака зарыта.

Что я, мудак, сделал:

  1. Профилирование, мать его. Включил все датчики: Application Insights, профилировщик памяти — ну, всю эту муть. И выясняется пиздец: во-первых, там внутри цикла на каждый чих летит отдельный запрос в базу, классический N+1, ебать его в сраку. А во-вторых, здоровенные JSONы сериализуются так, будто их рефлексия через жопу гоняет, аллокаций — овердохуища.

  2. Базу данных перестал ебать. Ну реально, что за дичь — в цикле стучаться за каждой записью. Вынес все IDшки, одним махом получил все нужные данные и склеил их в памяти. Смотри, как красота получилась:

// Раньше было (просто пиздец):
foreach (var item in items)
{
    var details = await _dbContext.Details.FirstOrDefaultAsync(d => d.ItemId == item.Id);
    // ... тут ещё какая-то хуйня
}

// А стало (нормально):
var itemIds = items.Select(i => i.Id).ToList();
var allDetails = await _dbContext.Details
    .Where(d => itemIds.Contains(d.ItemId))
    .ToDictionaryAsync(d => d.ItemId); // Всё, один запрос, и всё под рукой

foreach (var item in items)
{
    if (allDetails.TryGetValue(item.Id, out var details))
    {
        // ... и работаем спокойно
    }
}
  1. JSON перестал порождать мусор. Выкинул нахуй стандартную сериализацию, которая как черепаха, и подключил Source Generators из System.Text.Json. Это ж, блядь, магия — код сериализатора на этапе компиляции генерится, никакой рефлексии, скорость — огонь, память почти не жрёт.

  2. Кэш, куда ж без него. Накинул двухуровневый кэш: быстрый in-memory для локальных инстансов и Redis для распределёнки. Все эти справочники, которые почти не меняются, но в каждом запросе участвуют, — теперь оттуда летят, а не из базы каждый раз.

И что в итоге, спросишь? А в итоге API стал отвечать за ~50 мс, то есть в сорок раз быстрее, Карл! ЦПУ успокоился, нагрузка упала на 70%, а база данных вздохнула с облегчением — запросов к ней стало меньше на порядок. Задача была та ещё, но чертовски интересная: и поковыряться в глубинах пришлось, и разные подходы применить, а в конце ещё и бизнес такой довольный, что прям приятно.