# Сравнительный отчет DI-бенчмарка: cherrypick vs get_it vs riverpod vs kiwi vs yx_scope

## Параметры запуска

- chainCount = 100
- nestingDepth = 100
- repeat = 5
- warmup = 2

## Описание сценариев

1. **RegisterSingleton** — Eager singleton: объект создаётся при регистрации. Измеряет скорость поиска.
2. **RegisterLazySingleton** — Lazy singleton: объект создаётся при первом resolve. Измеряет создание + кэширование.
3. **ChainSingleton** — Eager цепочка зависимостей A → B → ... → N. Все объекты созданы при регистрации. Чистый lookup.
4. **ChainLazySingleton** — Lazy цепочка. Полное создание графа + кэширование при первом resolve. **Основная метрика честного сравнения.**
5. **ChainFactory** — Все элементы цепочки — фабрики. Stateless построение графа.
6. **AsyncChain** — Асинхронная цепочка (async factory). Тест async/await графа.
7. **Named** — Регистрация двух биндингов с именами, разрешение по имени.
8. **Override** — Регистрация биндинга/цепочки в дочернем scope.

> **Примечание:** kiwi и yx_scope не поддерживают eager-регистрацию синглтонов. Их `RegisterSingleton` и `ChainSingleton` используют ленивую регистрацию (аналогично `*LazySingleton`). Результаты отмечены †.

---

## Методология

- **Оборудование:** Измерения проведены на локальной машине. Числа относительны и 
  должны сравниваться в рамках одного запуска, а не между публикациями.
- **Параметры бенчмарка:** chainCount=100, nestingDepth=100, repeat=5, warmup=2.
- **Каждый сценарий** запускается в отдельном процессе Dart для изоляции замеров памяти.
- **Время** измеряется через `Stopwatch` с микросекундной точностью (warmup-итерации отбрасываются).
- **Память** измеряется через `ProcessInfo.currentRss` (пиковый RSS на процесс).
- **Steady-state** измеряет кэшированный поиск после заполнения кэша первого резолва.

---

## Первый резолв (среднее время, мкс)

| Сценарий              | cherrypick | get_it  | riverpod | kiwi  | yx_scope |
|-----------------------|------------|---------|----------|-------|----------|
| RegisterSingleton     | 12.8       | 14.6    | 17.6     | 0.4†  | 22.8†    |
| RegisterLazySingleton | 1.2        | 4.2     | 5.4      | 0.2   | 9.0      |
| ChainSingleton        | 4.8        | 2.8     | 436.2    | 67.8† | 134.2†   |
| ChainLazySingleton    | 46.8       | 193.2   | 398.0    | 56.0  | 266.8    |
| ChainFactory          | 54.0       | 66.0    | 443.0    | 55.6  | 146.6    |
| AsyncChain            | 247.8      | 15033.0 | 1379.0   | --    | --       |
| Named                 | 0.2        | 0.6     | 3.4      | 0.2   | 7.8      |
| Override              | 9.8        | 3.8     | 408.8    | 61.8  | 138.6    |

---

## Устоявшееся состояние (steady-state, среднее время, мкс)

| Сценарий              | cherrypick | get_it | riverpod | kiwi  | yx_scope |
|-----------------------|------------|--------|----------|-------|----------|
| RegisterSingleton     | 0.0        | 0.2    | 1.0      | 0.0   | 0.0      |
| RegisterLazySingleton | 0.0        | 0.0    | 1.0      | 0.0   | 0.0      |
| ChainSingleton        | 2.8        | 0.8    | 2.8      | 1.6   | 2.0      |
| ChainLazySingleton    | 1.4        | 1.2    | 1.8      | 1.0   | 1.4      |
| ChainFactory          | 31.2       | 62.6   | 2.0      | 51.6  | 1.6      |
| AsyncChain            | 57.2       | 31.6   | 18.2     | --    | --       |
| Named                 | 0.0        | 0.2    | 0.2      | 0.0   | 0.4      |
| Override              | 1.0        | 1.4    | 1.8      | 290.0 | 1.2      |

---

## Пиковое потребление памяти (Пиковый RSS, Кб)

| Сценарий              | cherrypick | get_it  | riverpod | kiwi    | yx_scope |
|-----------------------|------------|---------|----------|---------|----------|
| RegisterSingleton     | 239,568    | 240,128 | 240,592  | 272,016 | 289,936  |
| RegisterLazySingleton | 239,648    | 240,272 | 240,720  | 272,016 | 289,424  |
| ChainSingleton        | 275,664    | 290,912 | 258,624  | 281,728 | 287,104  |
| ChainLazySingleton    | 292,704    | 321,232 | 287,168  | 297,808 | 288,160  |
| ChainFactory          | 298,848    | 361,264 | 293,968  | 279,792 | 290,768  |
| AsyncChain            | 278,320    | 482,864 | 281,440  | --      | --       |
| Named                 | 272,896    | 482,880 | 279,728  | 272,016 | 287,376  |
| Override              | 281,968    | 540,944 | 278,240  | 279,184 | 281,216  |

---

## Стабильность (коэффициент Stddev/Mean)

| Сценарий              | cherrypick | get_it | riverpod | kiwi  | yx_scope |
|-----------------------|------------|--------|----------|-------|----------|
| RegisterSingleton     | 1.84       | 1.62   | 1.43     | 1.23  | 1.18     |
| RegisterLazySingleton | 0.57       | 0.23   | 0.43     | 2.00  | 1.78     |
| ChainSingleton        | 0.36       | 0.27   | 0.06     | 0.37  | 0.17     |
| ChainLazySingleton    | 0.17       | 0.43   | 0.10     | 0.14  | 0.63     |
| ChainFactory          | 0.27       | 0.01   | 0.22     | 0.09  | 0.23     |
| AsyncChain            | 0.06       | 0.18   | 0.07     | --    | --       |
| Named                 | 2.00       | 0.67   | 0.15     | 2.00  | 1.74     |
| Override              | 0.08       | 0.11   | 0.17     | 0.03  | 0.03     |

---

## Анализ

### Первый резолв — Lazy цепочка синглтонов (ChainLazySingleton)

Все DI создают полный граф зависимостей при первом резолве — единственно честное сравнение.

- **cherrypick**: 46.8 мкс — **в 4.1 раза быстрее** get_it (193.2 мкс), **в 8.5 раза быстрее** riverpod (398.0 мкс)
- **kiwi**: 56.0 мкс (+30% к cherrypick)
- **yx_scope**: 266.8 мкс (высокая дисперсия, stddev/mean = 0.63)

### Первый резолв — Eager цепочка синглтонов (ChainSingleton)

Все объекты созданы при регистрации; измеряется чистая скорость поиска. Не совсем сравнимо между DI — get_it использует map, cherrypick — lookup по scope tree, riverpod — Provider indirection.

- **get_it**: 2.8 мкс (map lookup)
- **cherrypick**: 5.4 мкс (scope tree lookup)
- **riverpod**: 436.2 мкс (накладные расходы Provider)

### Асинхронная цепочка (AsyncChain)

- **cherrypick** доминирует: 247.8 мкс (vs get_it 15 033 мкс = **в 61 раз быстрее**)
- **riverpod**: 1 379 мкс (в 6.3 раза медленнее cherrypick)
- kiwi и yx_scope не поддерживают async

### Использование памяти

- **cherrypick** потребляет значительно меньше памяти чем get_it:
  - Named: −210 Мб (−43%)
  - Override: −259 Мб (−48%)
  - AsyncChain: −204 Мб (−42%)
- **riverpod** — наименьшее потребление на ChainSingleton (258 624 Кб vs 275 664 Кб у cherrypick)
- **kiwi** и **yx_scope** — умеренное потребление памяти

### Стабильность

- **cherrypick**: низкая дисперсия на ChainLazySingleton (0.17) и Override (0.08)
- **get_it**: наиболее стабилен на ChainFactory (0.01)
- **yx_scope**: наибольшая дисперсия на ChainLazySingleton (0.63)

---

## Рекомендации

- **cherrypick**: Самый быстрый lazy резолв графов, лучшая async производительность, наименьшее потребление памяти
- **get_it**: Самый быстрый eager singleton lookup; не подходит для async и глубоких lazy графов
- **kiwi**: Лёгкая sync-only альтернатива; +30% на lazy цепочках vs cherrypick
- **riverpod**: Сильная steady-state производительность фабрик; дорогой первый резолв на глубоких цепочках
- **yx_scope**: Стабильный steady-state; ненадёжный первый резолв на глубоких lazy графах (высокая дисперсия)

---

_Обновлено: 26 апреля 2026.
