Skip to content

Performance optimization: zero GenServer.call hot path, pluggable strategies, CI/CD#5

Merged
nyo16 merged 7 commits into
masterfrom
feature/performance-optimization-v0.3.0
Mar 25, 2026
Merged

Performance optimization: zero GenServer.call hot path, pluggable strategies, CI/CD#5
nyo16 merged 7 commits into
masterfrom
feature/performance-optimization-v0.3.0

Conversation

@nyo16

@nyo16 nyo16 commented Mar 25, 2026

Copy link
Copy Markdown
Owner

Summary

  • 4.3–5.8x faster get_channel — rewrote hot path to eliminate GenServer.call bottleneck. Channels stored directly in ETS with O(1) indexed access and
    lock-free atomics round-robin.
  • Pluggable connection strategies — new Strategy behaviour with 3 built-in implementations: :round_robin (atomics), :random, :power_of_two
    (least-recently-used tiebreak). Custom strategies supported.
  • 10 bottlenecks fixed — O(n) scaling eliminated, telemetry loop rewritten as proper GenServer, stale scaling lock detection,
    crash_after_reconnect_attempt replaced with max_reconnect_attempts, ETS concurrency flags added.
  • New features — await_ready/2 for startup readiness, PoolState GenServer for ETS ownership, :persistent_term for zero-copy config reads.
  • CI/CD pipeline — GitHub Actions with compile, format, credo, test, dialyzer, and auto-publish to Hex on v* tag push.

Benchmark Results

┌───────────────────────┬───────────┬───────────┬─────────────┐
│ Metric │ v0.2.x │ v0.3.0 │ Improvement │
├───────────────────────┼───────────┼───────────┼─────────────┤
│ get_channel (pool=5) │ 473K ips │ 2.03M ips │ 4.3x faster │
├───────────────────────┼───────────┼───────────┼─────────────┤
│ get_channel (pool=25) │ 343K ips │ 1.99M ips │ 5.8x faster │
├───────────────────────┼───────────┼───────────┼─────────────┤
│ 100 concurrent p99 │ 1,035 μs │ 439 μs │ 58% lower │
├───────────────────────┼───────────┼───────────┼─────────────┤
│ Memory/call (pool=25) │ 1.65 KB │ 0.72 KB │ 56% less │
├───────────────────────┼───────────┼───────────┼─────────────┤
│ Pool.status │ 1.47M ips │ 3.71M ips │ 2.5x faster │
└───────────────────────┴───────────┴───────────┴─────────────┘

Pool size scaling: pool=25 was 38% slower than pool=5 in v0.2.x — now only 2% slower (O(n) eliminated).

Test Plan

  • 81 tests pass, 0 failures (mix test --exclude emulator)
  • Strategy tests cover round_robin, random, power_of_two
  • Existing pool scaling, telemetry, worker, config tests updated and passing
  • Benchee benchmarks runnable via mix run bench/get_channel_bench.exs
  • Run CI pipeline on PR
  • Integration test with Pub/Sub emulator (optional, requires Docker)

nyo16 added 7 commits March 25, 2026 07:08
…rver.call hot path

- Rewrite hot path to use ETS + atomics instead of Registry.lookup + GenServer.call
- Add pluggable connection strategies: round_robin, random, power_of_two
- Add PoolState GenServer for ETS ownership and persistent_term setup
- Add TelemetryReporter GenServer replacing recursive timer.sleep loop
- Add await_ready/2 for startup readiness signaling
- Add max_reconnect_attempts config replacing crash_after_reconnect_attempt
- Add stale scaling lock detection (30s timeout)
- Add Benchee benchmarks (bench/get_channel_bench.exs)
- Add GitHub Actions CI/CD with auto-publish to Hex on v* tag
- Update README with strategies docs, architecture diagram, benchmarks
- Update CHANGELOG with v0.3.0 entry
- Bump version to 0.3.0
- Fix alias ordering (alphabetical) in pool, worker, tests
- Replace explicit try with implicit try in config, pool, worker
- Extract scale_down helpers to reduce cyclomatic complexity
- Extract release_slot helper to reduce nesting depth
- Fix number underscore style (50051 -> 50_051) in tests
- All credo --strict clean, dialyzer passes with 0 errors
PLT files are machine-specific and should be generated locally
or cached in CI. Fixes dialyzer failure on GitHub Actions.
Wait for worker to be idle (GenServer.call) before sending second
disconnect message, instead of a fixed sleep. The worker blocks in
GRPC.Stub.connect (~5s timeout) and can't process messages during
that time. Also increase max_reconnect_attempts in test config to
prevent worker from crashing before the test completes.
@nyo16 nyo16 merged commit 1fc84e0 into master Mar 25, 2026
6 checks passed
@nyo16 nyo16 deleted the feature/performance-optimization-v0.3.0 branch March 25, 2026 11:40
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