swactor/CLAUDE/notes/progress.md
Developer 10cb0780b7 feat: stress tests, expanded benchmarks, and research extension
Cycle 2 of the competitor analysis improvement loop.

Research additions:
- Kameo: async on tokio, dual bounded/unbounded mailbox (default 64),
  Erlang-style supervision links, vtable dispatch
- Actix: custom Vyukov lock-free MPSC queue (why it's fastest),
  256-message assertion guard (validates our budget), Context-as-Future

New stress tests (6):
- Message ordering preserved under small budget (budget=8)
- Multi-threaded: 50 senders × 100 msgs to one receiver (4 threads)
- Concurrent spawn+send of 200 actors (4 threads)
- 50-level chain spawning across 2 workers
- Panic isolation: 10 panicking + 10 healthy actors (4 threads)
- Sustained throughput: 10 batches of 100 msgs with interleaved ticks

New benchmark groups:
- msg_size: throughput and send_latency by message size (8B-4KB)
- contention: fanin (1-100 senders), cross_worker (1-4 threads)

All 57 tests pass (51 runtime_api + 5 transport + 1 doctest).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 11:24:33 +00:00

3.9 KiB
Raw Blame History

Progress Log

Current Stage: Phase 1 — Research + First Improvement Cycle

Status: Cycle 2 COMPLETE

Plan Overview

  1. Phase 0: Codebase audit — understand current swactor architecture, existing tests, benchmarks ✅
  2. Phase 1: Broad survey + interleaved improvements
  3. Phase 2: Deeper improvements based on findings
  4. Phase 3: Testing methodology improvements
  5. Phase 4: Final evaluation & documentation

Completed This Session

Cycle 1: Fairness (Message Budget)

  • Research: Studied ractor, tokio, Erlang/OTP BEAM, Linux CFS/EEVDF, libuv
  • Finding: tick_all drained ENTIRE mailbox per actor per tick — critical fairness bug
    • BEAM uses 4000 reduction budget, tokio uses 128-op cooperative budget
    • Swactor had zero budget — one hot actor could starve all others on same worker
  • Implementation: Added actor_message_budget to RuntimeConfig (default: 64)
    • Modified tick_all to break after budget messages per actor
    • budget=0 means unlimited (backward compatible)
  • Tests: 3 new fairness tests (hot_actor_does_not_starve_cold_actor, unlimited_budget_drains_all, budget_messages_drain_across_multiple_ticks)
  • Benchmarks: Added fairness benchmark group (cold_latency_under_pressure, throughput_by_budget)
  • Fixes: Updated RuntimeConfig struct literals across crates (python, runtime-dashboard, mt_benchmarks)
  • Result: 45 tests pass (42 original + 3 new), all workspace crates compile

Cycle 2: Stress Tests, Benchmarks, Research Expansion

  • Research: Added Kameo and Actix analysis to synthesis
    • Actix uses custom Vyukov lock-free MPSC queue (why it's fastest)
    • Kameo has dual bounded/unbounded mailbox, default capacity 64
    • Both use vtable dispatch (not Box downcast)
    • Actix has 256-message assertion guard (validates our budget approach)
  • Stress tests: 6 new tests
    • message_ordering_preserved_under_budget — FIFO order with budget=8
    • mt_stress_many_senders_one_receiver — 50 senders × 100 msgs, 4 threads
    • mt_stress_concurrent_spawn_and_send — 200 concurrent spawn+send, 4 threads
    • mt_chain_spawning_under_load — 50-level chain across 2 workers
    • mt_panic_isolation_under_load — 10 panicking + 10 healthy actors, 4 threads
    • sustained_throughput_does_not_drop_messages — 10 batches × 100 msgs
  • Benchmarks: 2 new benchmark groups
    • msg_size: throughput and send_latency by message size (8B-4KB)
    • contention: fanin (1-100 senders to 1 sink), cross_worker (1-4 threads)
  • Result: 51 tests pass (42 original + 3 fairness + 6 stress), all workspace compiles

Research Notes

  • Full analysis in CLAUDE/notes/research_synthesis.md
  • Baseline benchmarks in CLAUDE/notes/baseline_benchmarks.md
  • Constraints in CLAUDE/notes/constraints.md

Next Steps

  • Cycle 2: Stress testing + property-based tests
    • Concurrent spawn+send stress tests
    • Multi-threaded fairness validation
    • Property: message ordering preserved under budget
    • Property: all messages eventually delivered with budget > 0
  • Cycle 3: Adaptive backoff with thread parking
    • Replace spinning with condvar-based parking (from tokio parker design)
    • Benchmark latency improvement under varying load
  • Cycle 4: Enhanced benchmarks
    • Message size sensitivity (8B, 64B, 256B, 1KB)
    • Latency percentiles (p50, p99, p999)
    • Many-to-one fanin contention
    • Cross-worker vs same-worker delivery comparison
  • Cycle 5: Work stealing exploration
    • Evaluate feasibility of actor migration between workers
    • BEAM two-tier approach: reactive steal + periodic migration

Open Questions

  • Should budget be configurable per-actor (not just per-runtime)?
  • Is 64 the right default budget? Benchmarks show budget=32 slightly faster for throughput
  • Thread parking: how to handle the notification mechanism without adding deps?

Blockers

  • (none)