Skip to content

Add benchmarks and micro-optimise the injection hot path#41

Draft
TomA-R wants to merge 1 commit intomasterfrom
claude/benchmarks-and-hot-path-optimisations
Draft

Add benchmarks and micro-optimise the injection hot path#41
TomA-R wants to merge 1 commit intomasterfrom
claude/benchmarks-and-hot-path-optimisations

Conversation

@TomA-R
Copy link
Member

@TomA-R TomA-R commented Mar 2, 2026

Summary

Applies four micro-optimisations to the injection hot path, all with passing tests and PHPStan level 6 clean

Benchmark setup

23 injectable fixture classes across three groups (no-constructor, 2-dep, 3–4-dep) backed by 20 pre-registered Pimple singletons. Total ~744 injections per simulated request.

Run with:

php benchmarks/bench.php [--requests N]

Three reported sections:

  1. Cold path — first injection per class (reflection + cache population)
  2. Warm path — subsequent injections with hot caches (steady-state throughput)
  3. Request simulation — fresh injector per repetition, reports min/median/mean/p95/max

Optimisations

# Location Change
1 Injector::create() Check empty($parameters) in create() itself and call buildParameterArrayFromContainer() directly, skipping the buildParameterArray() wrapper call on the common autowiring path
2 Injector::buildParameterArrayFromContainer() Drop $position key tracking — signature arrays are always 0-indexed sequential, so $parameters[] is equivalent and avoids keyed iteration overhead
3 CachingClassInspector Replace $constructorCache[$class] = [$result] wrapper trick with two arrays ($constructorCached presence flag + $constructorSignatures values), keeping the fast isset() check while removing the [0] offset dereference on every cache hit
4 Injector::$containerHasCache Cache container->has($type) results per FQCN — the container is sealed at bootstrap so this eliminates a PSR-11 method call + Pimple hash lookup on every repeated injection sharing the same container-registered dep types

Results (PHP 8.4, OPcache off, 744 injections/request)

Metric Before After Δ
Warm throughput 413k ops/s 731k ops/s +77%
Avg time per request 1.40 ms 1.01 ms −28%
Request sim throughput 530k ops/s 733k ops/s +38%

Test plan

  • ./vendor/bin/phpunit — 86 tests, 145 assertions pass
  • ./vendor/bin/phpstan analyse — no errors
  • php benchmarks/bench.php --requests 50 — runs cleanly, inspect throughput numbers

🤖 Generated with Claude Code

@TomA-R TomA-R force-pushed the claude/benchmarks-and-hot-path-optimisations branch from 35f9419 to a92b163 Compare March 2, 2026 01:07
All 86 tests pass, PHPStan level 6 clean.

Measured improvement (PHP 8.4, OPcache off, ~750 injections/request):
  Warm throughput:          413k → 666k ops/s  (+61%)
  Avg time per request:     1.40ms → 1.01ms    (−28%)
  Request sim throughput:   530k → 739k ops/s  (+39%)

1. Injector::create() — inline fast-path dispatch
   Skip the buildParameterArray() call entirely when no explicit parameters
   are provided (the common autowiring case), calling
   buildParameterArrayFromContainer() directly instead.

2. Injector::buildParameterArrayFromContainer() — drop $position key tracking
   The signature array is always 0-indexed sequential (built by
   ParameterInspector), so $parameters[] = ... produces the same result as
   $parameters[$position] = ... with less overhead per iteration.

3. Injector::$containerHasCache — cache container->has() per type
   The container is sealed at bootstrap; whether a given FQCN is registered
   does not change during a request. Caching the has() boolean per type
   eliminates a PSR-11 method call + Pimple hash lookup on every repeated
   injection that shares a container-registered dependency type.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@TomA-R TomA-R force-pushed the claude/benchmarks-and-hot-path-optimisations branch from a92b163 to 13c0d9d Compare March 2, 2026 02:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant