Skip to content

perf(runtime): coalesce external submission wakes - #1027

Merged
Coldwings merged 2 commits into
mainfrom
perf/coalesce-eventfd-wakes
Aug 12, 2026
Merged

perf(runtime): coalesce external submission wakes#1027
Coldwings merged 2 commits into
mainfrom
perf/coalesce-eventfd-wakes

Conversation

@Coldwings

@Coldwings Coldwings commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Description

Coalesce cross-thread task-submission notifications at the worker boundary so
bursts share one outstanding eventfd wake instead of issuing one write per
accepted task.

The worker clears the pending-wake claim immediately before a blocking poll and
then rechecks both external queues. Submissions published before the clear are
observed by that recheck; submissions after the clear claim a new notification
and interrupt the poll. This preserves the no-lost-wake guarantee without
reintroducing the former idle_-sampled lazy-wake race.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Performance improvement (optimization that improves speed/memory usage)
  • Documentation (changes to documentation, comments, or examples)
  • Refactoring (code changes that neither fix bugs nor add features)
  • Tests (adding or modifying tests)
  • Build/CI (changes to build system, CI configuration, or dependencies)

Related Issues

Closes #1026

Changes Made

Core Changes

  • Add a cache-line-isolated per-worker pending submission-wake claim.
  • Use release read-modify-write operations for every producer so the worker's
    acquire clear observes the full producer release sequence before rechecking
    the MPSC inbox and overflow queue.
  • Clear and recheck the claim before normal-idle and resize-draining polls;
    lifecycle stop/drain wakes remain unconditional.
  • Retry epoll and io_uring eventfd writes interrupted by EINTR, because a
    claimed wake cannot rely on a later coalesced producer to repair the write.
  • Add deterministic burst and clear-versus-block race tests for epoll and
    io_uring, plus an external-submission burst measurement in quick_benchmark.
  • Update README, API reference, performance guide, and changelog descriptions.

API Changes (if applicable)

None. Scheduling, affinity, and ownership contracts are unchanged.

Testing

Unit Tests

  • Added new tests for the changes
  • Updated existing tests if needed
  • All tests pass locally

Integration Tests

  • Tested with existing examples
  • Tested in real-world scenarios (if applicable)

Sanitizer Testing

  • Tested with ASAN (AddressSanitizer)
  • Tested with TSAN (ThreadSanitizer)
  • No new warnings or errors

Test Results

Strict GCC 12.2 build with developer warnings and warnings-as-errors:
  quick_benchmark, elio_tests, elio_tests_asan, elio_tests_tsan: PASS

Normal full suite:
  791 test cases, 12082 assertions: PASS

Wake-focused normal / ASAN / TSAN:
  2 test cases, 32 assertions each: PASS

ASAN scheduler suite:
  77 test cases, 579 assertions: PASS

TSAN scheduler suite:
  77 test cases, 579 assertions: PASS (no race reports)

Clear-versus-block regression stress:
  epoll and io_uring, 100 consecutive runs: PASS

Scheduler service benchmark --smoke:
  io_uring, 3 trials: PASS

Three paired, CPU-pinned quick-benchmark runs measured the producer-side
external submission burst at 686.42 ns/submit on main and 155.38 ns/submit on
this branch: a 77.4% reduction (4.42x). Scheduler reschedule remained stable at
22.66 ns on main and 22.48 ns on this branch. Timing values are reported as
local evidence only and are not CI thresholds.

Checklist

Code Quality

  • My code follows the project's code style
  • I have added/updated comments for complex logic
  • I have removed any debug code, TODOs, or commented-out code
  • My changes generate no new warnings

Documentation

  • I have updated documentation (wiki, README, code comments)
  • I have added examples for new features (if applicable)
  • I have updated API documentation (if applicable)

Testing

  • I have added tests that prove my fix is effective or my feature works
  • New and existing unit tests pass locally with my changes
  • I have tested with ASAN and TSAN

Compatibility

  • My changes are backward compatible (or I've documented breaking changes)
  • I have considered the impact on existing users
  • I have updated CHANGELOG.md (if applicable)

Performance (if applicable)

  • I have considered the performance impact
  • I have added benchmarks for performance-critical changes

Screenshots / Diagrams

Not applicable.

Additional Notes

Wake coalescing is intentionally separate from scheduler service-quantum work:
this PR removes redundant producer work but does not change how long a worker
may execute its local runnable deque before servicing I/O or external queues.

Reviewer Guidance

Areas requiring special attention:

  • The release-sequence argument in wake_for_submission(); replacing the
    exchange with a failed compare-and-exchange would not publish a skipped
    producer's queue write.
  • The clear-then-recheck ordering before every production blocking poll.
  • Lifecycle wakes remaining outside the submission-coalescing state.

Questions for reviewers:

  • Is there any production blocking-poll path not covered by the reset/recheck
    handshake?
  • Are the epoll and io_uring eventfd semantics still equivalent for this
    worker-level claim?

Thank you for contributing to Elio! 🎉

Copilot AI balanced review requested due to automatic review settings August 12, 2026 18:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Optimizes cross-thread scheduling by coalescing worker wake notifications while preserving no-lost-wake behavior.

Changes:

  • Adds per-worker wake coalescing and queue rechecks before polling.
  • Retries interrupted backend eventfd writes.
  • Adds tests, benchmarking, and documentation updates.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
include/elio/runtime/worker_thread.hpp Adds pending-wake state and helpers.
include/elio/runtime/scheduler.hpp Resets wake claims before blocking polls.
include/elio/io/epoll_backend.hpp Retries eventfd writes on EINTR.
include/elio/io/io_uring_backend.hpp Retries eventfd writes on EINTR.
tests/unit/test_scheduler.cpp Adds wake coalescing and race tests.
examples/quick_benchmark.cpp Benchmarks external submission bursts.
README.md Documents coalesced wakes and benchmark coverage.
CHANGELOG.md Records the optimization.
wiki/API-Reference.md Updates worker wake semantics.
wiki/Performance-Tuning.md Explains wake coalescing and performance effects.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tests/unit/test_scheduler.cpp Outdated
Comment thread tests/unit/test_scheduler.cpp Outdated
@Coldwings

Copy link
Copy Markdown
Owner Author

@copilot Please review the current head only. Please do not modify code or push commits.

Copilot AI commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

@copilot Please review the current head only. Please do not modify code or push commits.

Reviewed the current head only. I don’t see additional actionable issues in the updated wake-coalescing and regression-test changes.

@Coldwings
Coldwings merged commit 64a085a into main Aug 12, 2026
11 checks passed
@Coldwings
Coldwings deleted the perf/coalesce-eventfd-wakes branch August 12, 2026 20:25
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.

[Performance] Coalesce cross-thread eventfd wakes without lost notifications

3 participants