mirror of
https://github.com/pese-git/cherrypick.git
synced 2026-05-16 10:10:43 +00:00
9.1 KiB
9.1 KiB
Сравнительный отчет DI-бенчмарка: cherrypick vs get_it vs riverpod vs kiwi vs yx_scope
Параметры запуска
- chainCount = 100
- nestingDepth = 100
- repeat = 5
- warmup = 2
Описание сценариев
- RegisterSingleton — Eager singleton: объект создаётся при регистрации. Измеряет скорость поиска.
- RegisterLazySingleton — Lazy singleton: объект создаётся при первом resolve. Измеряет создание + кэширование.
- ChainSingleton — Eager цепочка зависимостей A → B → ... → N. Все объекты созданы при регистрации. Чистый lookup.
- ChainLazySingleton — Lazy цепочка. Полное создание графа + кэширование при первом resolve. Основная метрика честного сравнения.
- ChainFactory — Все элементы цепочки — фабрики. Stateless построение графа.
- AsyncChain — Асинхронная цепочка (async factory). Тест async/await графа.
- Named — Регистрация двух биндингов с именами, разрешение по имени.
- 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.