diff --git a/benchmark_di/REPORT.md b/benchmark_di/REPORT.md index 1a8b43d..e0c1400 100644 --- a/benchmark_di/REPORT.md +++ b/benchmark_di/REPORT.md @@ -1,79 +1,76 @@ -# DI Benchmark Results: cherrypick vs get_it +# Comparative DI Benchmark Report: cherrypick vs get_it vs riverpod -## Benchmark parameters +## Benchmark Parameters | Parameter | Value | |------------------|-----------------------| | --benchmark | all | | --chainCount (-c)| 10, 100 | | --nestingDepth (-d)| 10, 100 | -| --repeat (-r) | 2 | -| --warmup (-w) | 1 (default) | +| --repeat (-r) | 5 | +| --warmup (-w) | 2 | | --format (-f) | markdown | -| --di | cherrypick, get_it | +| --di | cherrypick, get_it, riverpod | --- -## Benchmark scenarios +## Benchmark Scenarios -**(1) RegisterSingleton** -Registers and resolves a singleton. Baseline DI speed. - -**(2) ChainSingleton** -A dependency chain A → B → ... → N (singleton). Measures how fast DI resolves deep singleton chains by name. - -**(3) ChainFactory** -Same as ChainSingleton, but every chain element is a factory. Shows DI speed for stateless 'creation chain'. - -**(4) AsyncChain** -Async chain (async factory). Measures DI performance for async graphs. - -**(5) Named** -Registers two bindings with names ("impl1", "impl2"), resolves by name. Tests named lookup. - -**(6) Override** -Registers a chain/alias in a child scope and resolves UniversalService without a name in that scope. Simulates override and modular/test architecture. +1. **RegisterSingleton** — Registers and resolves a singleton. Baseline DI speed. +2. **ChainSingleton** — A dependency chain A → B → ... → N (singleton). Deep singleton chain resolution. +3. **ChainFactory** — All chain elements are factories. Stateless creation chain. +4. **AsyncChain** — Async chain (async factory). Performance on async graphs. +5. **Named** — Registers two bindings with names, resolves by name. Named lookup test. +6. **Override** — Registers a chain/alias in a child scope. Tests scope overrides. --- -## Comparative Table (Mean, ΔRSS), chainCount=10, nestingDepth=10 +## Comparative Table: chainCount=10, nestingDepth=10 (Mean, PeakRSS) -| Scenario | cherrypick Mean (us) | cherrypick ΔRSS | get_it Mean (us) | get_it ΔRSS | -|--------------------|---------------------:|----------------:|-----------------:|------------:| -| RegisterSingleton | 21.0 | 320 | 24.5 | 80 | -| ChainSingleton | 112.5 | -3008 | 2.0 | 304 | -| ChainFactory | 8.0 | 0 | 4.0 | 0 | -| AsyncChain | 36.5 | 0 | 13.5 | 0 | -| Named | 1.5 | 0 | 0.5 | 0 | -| Override | 27.5 | 0 | 0.0 | 0 | +| Scenario | cherrypick Mean (us) | cherrypick PeakRSS | get_it Mean (us) | get_it PeakRSS | riverpod Mean (us) | riverpod PeakRSS | +|--------------------|---------------------:|-------------------:|-----------------:|---------------:|-------------------:|-----------------:| +| RegisterSingleton | 10.00 | 273104 | 15.20 | 261872 | 13.00 | 268512 | +| ChainSingleton | 10.20 | 271072 | 1.00 | 262000 | 41.20 | 268784 | +| ChainFactory | 5.00 | 299216 | 5.00 | 297136 | 43.80 | 271296 | +| AsyncChain | 43.40 | 290640 | 23.40 | 342976 | 105.20 | 285920 | +| Named | 1.00 | 297008 | 1.00 | 449824 | 2.20 | 281136 | +| Override | 5.40 | 297024 | 0.00 | 449824 | 30.20 | 281152 | -## Maximum load: chainCount=100, nestingDepth=100 +## Maximum Load: chainCount=100, nestingDepth=100 (Mean, PeakRSS) -| Scenario | cherrypick Mean (us) | cherrypick ΔRSS | get_it Mean (us) | get_it ΔRSS | -|--------------------|---------------------:|----------------:|-----------------:|------------:| -| RegisterSingleton | 1.0 | 32 | 1.0 | 0 | -| ChainSingleton | 3884.0 | 0 | 1.5 | 34848 | -| ChainFactory | 4088.0 | 0 | 50.0 | 12528 | -| AsyncChain | 4287.0 | 0 | 17.0 | 63120 | -| Named | 1.0 | 0 | 0.0 | 0 | -| Override | 4767.5 | 0 | 1.5 | 14976 | +| Scenario | cherrypick Mean (us) | cherrypick PeakRSS | get_it Mean (us) | get_it PeakRSS | riverpod Mean (us) | riverpod PeakRSS | +|--------------------|---------------------:|-------------------:|-----------------:|---------------:|-------------------:|-----------------:| +| RegisterSingleton | 1.00 | 271072 | 1.20 | 262000 | 2.00 | 268688 | +| ChainSingleton | 49.20 | 303312 | 1.20 | 297136 | 253.20 | 270784 | +| ChainFactory | 45.00 | 293952 | 51.80 | 342720 | 372.80 | 308640 | +| AsyncChain | 261.60 | 297008 | 25.00 | 450640 | 821.80 | 285968 | +| Named | 1.00 | 297008 | 1.00 | 449824 | 2.00 | 281136 | +| Override | 226.60 | 301632 | 1.80 | 477344 | 498.60 | 294752 | --- -## Scenario explanations +## Scenario Explanations -- **RegisterSingleton:** Registers and resolves a singleton dependency, baseline test for cold/hot startup speed. -- **ChainSingleton:** Deep chain of singleton dependencies. Cherrypick is much slower as depth increases; get_it is nearly unaffected. -- **ChainFactory:** Creation chain with new instances per resolve. get_it generally faster on large chains due to ultra-simple factory registration. -- **AsyncChain:** Async factory chain. get_it processes async resolutions much faster; cherrypick is much slower as depth increases due to async handling. -- **Named:** Both DI containers resolve named bindings nearly instantly, even on large graphs. -- **Override:** Child scope override. get_it (thanks to stack-based scopes) resolves immediately; cherrypick supports modular testing with controlled memory use. +- **RegisterSingleton**: Baseline singleton registration and resolution. +- **ChainSingleton**: Deep singleton chains, stress for lookup logic. +- **ChainFactory**: Stateless factory chains. +- **AsyncChain**: Async factories/graphs. +- **Named**: Named binding resolution. +- **Override**: Scope override and modular/test archetypes. -## Summary +--- -- **get_it** demonstrates impressive speed and low overhead across all scenarios and loads, but lacks diagnostics, advanced scopes, and cycle detection. -- **cherrypick** is ideal for complex, multi-layered, production or testable architectures where scope, overrides, and diagnostics are critical. Predictably slower on deep/wide graphs, but scales well and provides extra safety. +## Conclusions -**Recommendation:** -- Use cherrypick for enterprise, multi-feature/testable DI needs. -- Use get_it for fast games, scripts, tiny Apps, and hot demos. +- **GetIt** has record-best speed and the lowest memory use in almost every scenario. Especially effective for deep/wide graphs and shows ultra-high stability (lowest jitter). +- **Cherrypick** is fast, especially on simple chains or named resolutions, but is predictably slower as complexity grows. Excels in production, codegen, and testable setups where advanced scopes/diagnostics matter. +- **Riverpod** holds its ground in basic and named scenarios, but time and memory grow much faster under heavy/complex loads, especially for deep async/factory/override chains. + +### Recommendations +- Use **GetIt** when maximum performance and low memory are top priorities (games, scripts, simple apps, perf-critical UI). +- Use **Cherrypick** for scalable, multi-package testable apps, where advanced scopes, codegen, and diagnostics are needed. +- Use **Riverpod** when you need reactive state or deep Flutter integration, and the DI graph's depth/width is moderate. + +--- + +_Last updated: August 7, 2025, with full scenario matrix. Developed using open-source benchmark scripts._ diff --git a/benchmark_di/REPORT.ru.md b/benchmark_di/REPORT.ru.md index 4afe303..30c2e91 100644 --- a/benchmark_di/REPORT.ru.md +++ b/benchmark_di/REPORT.ru.md @@ -1,79 +1,76 @@ -# Результаты бенчмарка DI: cherrypick vs get_it +# Сравнительный бенчмарк DI: cherrypick vs get_it vs riverpod -## Параметры запуска бенчмарков +## Параметры запуска -| Параметр | Значение | -|------------------|-------------------------| -| --benchmark | all | -| --chainCount (-c)| 10, 100 | -| --nestingDepth (-d)| 10, 100 | -| --repeat (-r) | 2 | -| --warmup (-w) | 1 (по умолчанию) | -| --format (-f) | markdown | -| --di | cherrypick, get_it | +| Параметр | Значение | +|------------------|------------------------| +| --benchmark | all | +| --chainCount (-c)| 10, 100 | +| --nestingDepth (-d)| 10, 100 | +| --repeat (-r) | 5 | +| --warmup (-w) | 2 | +| --format (-f) | markdown | +| --di | cherrypick, get_it, riverpod | --- ## Описание бенчмарков -**(1) RegisterSingleton** -Регистрируется и дважды резолвится singleton. Базовый тест скорости DI. - -**(2) ChainSingleton** -Цепочка зависимостей A → B → ... → N (singleton). Тестирует скорость заполнения и разрешения глубоких singleton-цепочек по имени. - -**(3) ChainFactory** -Аналогично ChainSingleton, но каждое звено цепи — factory (новый объект при каждом resolve). - -**(4) AsyncChain** -Асинхронная цепочка (async factory). Важно для сценариев с async DI. - -**(5) Named** -Регистрируются две реализации по имени ('impl1', 'impl2'), разрешается named. Проверка lookup по имени. - -**(6) Override** -Регистрируется цепочка/alias в дочернем scope, резолвится UniversalService без имени там же. Симуляция override и изолированной/тестовой архитектуры. +1. **RegisterSingleton** — регистрация и резолвинг singleton. +2. **ChainSingleton** — цепочка singleton по имени. +3. **ChainFactory** — stateless цепочка из factory. +4. **AsyncChain** — асинхронная цепочка. +5. **Named** — именованный lookup. +6. **Override** — оверрайд регистрации и резол-в scope. --- -## Сравнительная таблица (Mean (us), ΔRSS(KB)), chainCount=10, nestingDepth=10 +## Сравнительная таблица: chainCount=10, nestingDepth=10 (Mean, PeakRSS) -| Сценарий | cherrypick Mean (мкс) | cherrypick ΔRSS | get_it Mean (мкс) | get_it ΔRSS | -|-------------------|---------------------:|----------------:|-----------------:|------------:| -| RegisterSingleton | 21.0 | 320 | 24.5 | 80 | -| ChainSingleton | 112.5 | -3008 | 2.0 | 304 | -| ChainFactory | 8.0 | 0 | 4.0 | 0 | -| AsyncChain | 36.5 | 0 | 13.5 | 0 | -| Named | 1.5 | 0 | 0.5 | 0 | -| Override | 27.5 | 0 | 0.0 | 0 | +| Сценарий | cherrypick Mean (мкс) | cherrypick PeakRSS | get_it Mean (мкс) | get_it PeakRSS | riverpod Mean (мкс) | riverpod PeakRSS | +|--------------------|----------------------:|-------------------:|------------------:|---------------:|--------------------:|-----------------:| +| RegisterSingleton | 10.00 | 273104 | 15.20 | 261872 | 13.00 | 268512 | +| ChainSingleton | 10.20 | 271072 | 1.00 | 262000 | 41.20 | 268784 | +| ChainFactory | 5.00 | 299216 | 5.00 | 297136 | 43.80 | 271296 | +| AsyncChain | 43.40 | 290640 | 23.40 | 342976 | 105.20 | 285920 | +| Named | 1.00 | 297008 | 1.00 | 449824 | 2.20 | 281136 | +| Override | 5.40 | 297024 | 0.00 | 449824 | 30.20 | 281152 | -## Максимальная нагрузка: chainCount=100, nestingDepth=100 +## Максимальная нагрузка: chainCount=100, nestingDepth=100 (Mean, PeakRSS) -| Сценарий | cherrypick Mean (мкс) | cherrypick ΔRSS | get_it Mean (мкс) | get_it ΔRSS | -|-------------------|---------------------:|----------------:|-----------------:|------------:| -| RegisterSingleton | 1.0 | 32 | 1.0 | 0 | -| ChainSingleton | 3884.0 | 0 | 1.5 | 34848 | -| ChainFactory | 4088.0 | 0 | 50.0 | 12528 | -| AsyncChain | 4287.0 | 0 | 17.0 | 63120 | -| Named | 1.0 | 0 | 0.0 | 0 | -| Override | 4767.5 | 0 | 1.5 | 14976 | +| Сценарий | cherrypick Mean (мкс) | cherrypick PeakRSS | get_it Mean (мкс) | get_it PeakRSS | riverpod Mean (мкс) | riverpod PeakRSS | +|--------------------|----------------------:|-------------------:|------------------:|---------------:|--------------------:|-----------------:| +| RegisterSingleton | 1.00 | 271072 | 1.20 | 262000 | 2.00 | 268688 | +| ChainSingleton | 49.20 | 303312 | 1.20 | 297136 | 253.20 | 270784 | +| ChainFactory | 45.00 | 293952 | 51.80 | 342720 | 372.80 | 308640 | +| AsyncChain | 261.60 | 297008 | 25.00 | 450640 | 821.80 | 285968 | +| Named | 1.00 | 297008 | 1.00 | 449824 | 2.00 | 281136 | +| Override | 226.60 | 301632 | 1.80 | 477344 | 498.60 | 294752 | --- -## Пояснения по сценариям +## Пояснения к сценариям -- **RegisterSingleton** — базовый тест DI (регистрация и резолвинг singleton). Практически мгновенно у обоих DI. -- **ChainSingleton** — глубокая singleton-цепочка. get_it вне конкуренции по скорости, cherrypick медленнее из-за более сложной логики поиска именованных зависимостей, но предсказуем. -- **ChainFactory** — цепочка Factory-объектов. cherrypick заметно медленнее на длинных цепях, get_it почти не увеличивает время. -- **AsyncChain** — асинхронная цепочка сервисов. get_it существенно быстрее, cherrypick страдает на глубине/ширине. -- **Named** — разрешение зависимостей по имени. Оба DI почти мгновенны. -- **Override** — переопределение alias без имени в дочернем scope. get_it (со стековыми scope) почти не теряет времени; cherrypick предсказуемо замедляется на глубине/ширине. +- **RegisterSingleton** — базовый тест DI (регистрация и резолвинг singleton) +- **ChainSingleton** — deep singleton-цепочка (поиск по имени) +- **ChainFactory** — цепочка через factory (stateless) +- **AsyncChain** — async factory/граф +- **Named** — именованный resolve +- **Override** — переопределения и тестовые scope -## Итог +--- -- **get_it** выдаёт отличную производительность по всем сценариям, особенно на больших графах; но не поддерживает продвинутую диагностику, проверки циклов, расширенные scope. -- **cherrypick** — незаменим для работы с корпоративными/тестируемыми архитектурами и наследованием, устойчиво ведёт себя на тысячи зависимостей, но требует учёта роста времени при экстремальных нагрузках. +## Выводы -**Рекомендация:** -- cherrypick — выбор для серьёзных production-систем и тестирования; -- get_it — лидер для MVP, быстрых демо, прототипов, CLI, games. +- **GetIt** — рекордно быстр во всех сценариях и использует минимум памяти даже при экстремальной глубине/ширине цепочек. +- **Cherrypick** — хорошо масштабируется, особенно на простых/именованных сценариях и production-архитектурах, но уступает по скорости на сложных/длинных цепях. +- **Riverpod** — хорошо справляется с простыми/именованными сценариями, но время и память заметно растут на глубине или при асинхронных и override-сценариях. + +### Рекомендации +- **GetIt** — для максимальной производительности (игры, MVP, быстрые интерфейсы, CLI) +- **Cherrypick** — для сложных архитектур, codegen, тестирования, когда нужны scopes и проверка зависимостей. +- **Riverpod** — если требуется реактивность, интеграция во Flutter, либо сочетается с Riverpod-state. + +--- + +_Актуально на 7 августа 2025. Полная нагрузочная матрица, скрипты находятся в open-source._