---
name: detect-bottlenecks
description: Використовуйте цей навик для виявлення та усунення вузьких місць продуктивності у Laravel/PHP-проєкті. Аналізує CPU, памʼять, I/O, БД-запити, черги, кеш та lock-contention. Ключові тригери: bottleneck, performance, продуктивність, оптимізуй, повільно, slow, optimize, speed up, вузьке місце.
metadata:
  author: linecore
  version: "1.0"
  package: service-market
  updated: "2026-05-07"
---

# Виявлення вузьких місць продуктивності

## Швидка активація (для запитів будь-якою мовою)
- **Використовувати, коли**: є скарги на повільну роботу, потрібна оптимізація коду, аналіз продуктивності.
- **RU сигнали**: узкое место, оптимизация производительности, медленно работает, найди bottleneck
- **EN signals**: performance bottleneck, slow query, optimize, speed up, memory leak, high CPU
- **UA сигнали**: вузьке місце, оптимізація, повільно працює, знайди проблему з продуктивністю
- **Не використовувати, коли**: потрібна лише рефакторинг-чистка (refactor-safe-local) або архітектурна перебудова (refactor-global-architecture).

---

## 1. Зони аналізу

### CPU
- Computation-heavy loops без раннього виходу
- Regex без лімітів / без кешування скомпільованих патернів
- Надлишкова серіалізація / JSON-encode великих обʼєктів
- Невикористані обчислення (lazy evaluation можлива?)
- Синхронні операції, які можна перенести у Job/Queue

### Памʼять
- N+1 через eager loading: `with()` / `load()` відсутні
- `chunk()` / `cursor()` замість `get()` для великих колекцій
- Накопичення стану в static properties між запитами (особливо у worker-процесах)
- Ресурси без явного `fclose()` / `unset()`
- Великі масиви/колекції, що зберігаються в сесії або кеші

### I/O (диск і мережа)
- Файловий I/O у циклі
- Синхронні HTTP-запити до зовнішніх сервісів (без queue/async)
- Читання config/env у runtime (замість кешованого `config()`)
- Відсутність HTTP keep-alive або connection pool для external API

### БД (Eloquent / Query Builder / Raw)
- N+1 queries: відношення без `with()` / `whenLoaded()` у Resource
- Missing indexes: `EXPLAIN` / `EXPLAIN ANALYZE` для повільних запитів
- `SELECT *` там, де потрібен `SELECT id, name, ...`
- Відсутність paginate/chunk для великих вибірок
- Транзакції всередині циклів (batch insert/update замість поштучного)
- Полнотекстовий пошук через `LIKE '%...%'` замість Scout/OpenSearch
- Агрегації в PHP замість SQL (`COUNT`, `SUM`, `GROUP BY`)

### Кеш (Redis / File)
- Відсутність кешування для дорогих запитів або зовнішніх API
- Cache stampede без `remember()` з atomic lock
- Занадто короткий TTL → постійні промахи
- Відсутність тегованого кешу для пов'язаних ключів

### Черги / Jobs
- Важка логіка в синхронному запиті замість `dispatch()`
- Відсутність `ShouldBeUnique` для jobs, що не мають виконуватись паралельно
- Великі payload у job (передавати ID, не model)
- Відсутність `onQueue()` / `onConnection()` пріоритизації

### Lock Contention
- Pessimistic locking (`lockForUpdate`) у тривалих транзакціях
- Відсутність `optimistic locking` для high-concurrency оновлень
- Race condition у cache-miss сценаріях (без atomic `Cache::lock()`)

---

## 2. Процес аналізу

1. **Зібрати контекст**: маршрут / команда / Job / listener, що повільно виконується.
2. **Профіль вхідних даних**: обсяг рядків у БД, частота викликів, concurrent users.
3. **Знайти потенційні зони**: пройтися по зонах п.1 стосовно переданого коду.
4. **Підтвердити гіпотези**: `EXPLAIN` для SQL, `Telescope` / `Debugbar` для запитів, `top`/`htop` для CPU/RAM.
5. **Оцінити вплив**: скільки ms / MB / RPS дає кожне вузьке місце.
6. **Побудувати план виправлення** по пріоритету (impact / effort).

---

## 3. Формат звіту

```
## Аналіз продуктивності: [файл / endpoint / команда]

### Знайдені вузькі місця

| # | Зона     | Опис проблеми             | Severity | Impact |
|---|----------|---------------------------|----------|--------|
| 1 | БД       | N+1 у ProductResource     | HIGH     | ~200ms |
| 2 | Памʼять  | get() на 50k рядків       | MEDIUM   | ~80MB  |
| 3 | Кеш      | Немає кешу для price calc | LOW      | ~10ms  |

### Деталі та виправлення

**[#1] N+1 у ProductResource**
- Причина: `$this->variants` без `whenLoaded()`
- Виправлення: `->with('variants')` у контролері + `whenLoaded()` у ресурсі
- Приклад коду: [конкретний diff]

...

### Рекомендації з моніторингу
- Додати `slow_query_log` у MySQL (> 100ms)
- Telescope → Query Watcher для staging
- Підключити Scout/OpenSearch для пошукових запитів
```

---

## 4. Правила при виправленні

- Дотримуватись `coding-standards-always` при будь-якій зміні коду.
- Не рефакторити поза зоною вузького місця без окремого запиту.
- Batch-зміни у БД — завжди через транзакцію.
- Кожна оптимізація має бути вимірюваною (до/після).
- Не вводити нові залежності без погодження.
