Files
cherrypick/benchmark_di/REPORT_v2.ru.md

149 lines
9.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Сравнительный отчет 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.