Skip to content

perf(core): reduce noop wait signal overhead#2690

Draft
Ahoo-Wang wants to merge 5 commits into
mainfrom
codex/noop-benchmark-performance
Draft

perf(core): reduce noop wait signal overhead#2690
Ahoo-Wang wants to merge 5 commits into
mainfrom
codex/noop-benchmark-performance

Conversation

@Ahoo-Wang

@Ahoo-Wang Ahoo-Wang commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add noop wait-notify benchmark diagnostics for sent waits so the send-and-wait-sent path can be measured independently.
  • Optimize waitingLast() for the common single empty-result signal case by returning the original signal instead of copying and merging maps.
  • Add a dedicated DefaultCommandGateway.sendAndWaitForSent fast path that bypasses generic wait strategy registration, wait headers, sink subscription, and waitingLast() for the sent convenience API.
  • Add regression tests for sent fast-path side effects, error mapping, void command support, single-signal identity, failed prior-stage fallback, and merged wait results.

Changes

  • wow-benchmarks: includes WaitNotifyComponentBenchmark in the smoke suite and adds sent wait propagation/notification benchmarks.
  • wow-core: extracts wait signal result merging helpers and uses a single-signal fast path in WaitingFor.waitingLast().
  • wow-core: updates WaitingForAfterProcessed.waitingLast() to share merge logic while preserving target-stage metadata.
  • wow-core: overrides sendAndWaitForSent in DefaultCommandGateway to return a direct SENT result after command bus send succeeds.
  • docs/superpowers: records the noop benchmark performance designs used for the implementation.

Benchmark Result

Quick E2E directional result for CommandWriteE2EBenchmark.sendAndWaitSent (scenario=noop-store):

Threads Before After Change
1 throughput 770,645.11 ops/s 1,249,238.49 ops/s +62.10%
1 allocation 6060.2 B/op 3348.3 B/op -44.75%
4 throughput 1,190,882.30 ops/s 1,392,839.05 ops/s +16.96%
4 allocation 6063.1 B/op 3350.2 B/op -44.74%

Processed noop remained in the same allocation range and is not claimed as optimized by the sent fast path:

Benchmark Threads Throughput Allocation
sendAndWaitProcessed(noop-store) 1 83,973.97 ops/s 6946.8 B/op
sendAndWaitProcessed(noop-store) 4 152,762.87 ops/s 6942.4 B/op

Testing

  • ./gradlew :wow-core:test --tests "me.ahoo.wow.command.DefaultCommandGatewayTest"
  • ./gradlew :wow-core:test --tests "me.ahoo.wow.command.wait.stage.WaitingForStageNotificationTest" --tests "me.ahoo.wow.command.wait.chain.SimpleWaitingForChainNotifyTest"
  • ./gradlew :wow-core:test --tests "me.ahoo.wow.command.wait.*"
  • ./gradlew :wow-core:test
  • ./gradlew :wow-core:check
  • ./gradlew :wow-benchmarks:benchmarkSmoke --stacktrace
  • ./gradlew :wow-benchmarks:benchmarkQuickComponentThread1 --stacktrace
  • ./gradlew :wow-benchmarks:benchmarkQuickE2E :wow-benchmarks:generateBenchmarkReport --stacktrace

Risk & Compatibility

  • No public API signature or dependency changes.
  • sendAndWaitForSent(command) no longer writes command_wait_* headers or registers a wait strategy; this is intentional for the sent convenience API because it completes at gateway send success.
  • Generic send(command, waitStrategy), sendAndWait(command, waitStrategy), streaming waits, and downstream stage propagation keep the existing wait strategy behavior.
  • The waitingLast() single empty-result fast path returns the original emitted WaitSignal, relying on emitted signals not being mutated after emission.

Review Notes

  • Review the DefaultCommandGateway.sendAndWaitForSent override as the main behavior change.
  • Review WaitingForAfterProcessed.waitingLast() fallback path; it preserves failed previous-stage signals when the target stage never arrives.
  • Local benchmark report output was generated for validation but is not included in this PR.

@codacy-production

codacy-production Bot commented Jun 9, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 4 complexity

Metric Results
Complexity 4

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@codecov

codecov Bot commented Jun 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.66667% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.65%. Comparing base (c1bdcb8) to head (515aaf1).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...main/kotlin/me/ahoo/wow/command/wait/WaitingFor.kt 71.42% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #2690      +/-   ##
============================================
- Coverage     92.67%   92.65%   -0.02%     
- Complexity     4255     4262       +7     
============================================
  Files           753      753              
  Lines         13493    13511      +18     
  Branches        963      966       +3     
============================================
+ Hits          12504    12519      +15     
- Misses          607      609       +2     
- Partials        382      383       +1     
Flag Coverage Δ
contract 52.53% <80.00%> (?)
integration 76.13% <ø> (?)
local 82.18% <86.66%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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