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