perf(runtime): transfer existing tasks directly - #1031
Conversation
There was a problem hiding this comment.
Pull request overview
Adds direct transfer of lazy tasks to spawn APIs, avoiding wrapper coroutine overhead while preserving callable lifetime safety.
Changes:
- Adds direct-task scheduler and namespace-level overloads.
- Preserves join, cancellation, affinity, and rejection behavior.
- Adds tests, benchmarks, and documentation.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
include/elio/runtime/scheduler.hpp |
Implements direct task admission. |
include/elio/runtime/spawn.hpp |
Adds namespace-level overloads. |
include/elio/coro/promise_base.hpp |
Adds allocation-count test instrumentation. |
tests/unit/test_task.cpp |
Tests transfer, affinity, rejection, and allocation count. |
tests/unit/test_cancellation_context.cpp |
Tests direct-root cancellation. |
examples/quick_benchmark.cpp |
Benchmarks callable versus direct spawning. |
README.md |
Documents direct spawn usage. |
CHANGELOG.md |
Records the new API. |
wiki/API-Reference.md |
Documents overloads and examples. |
wiki/API-Contracts.md |
Defines ownership and cancellation contracts. |
wiki/Core-Concepts.md |
Explains direct root-frame transfer. |
wiki/Performance-Tuning.md |
Provides performance guidance. |
Suppressed comments (1)
examples/quick_benchmark.cpp:166
- As above, the no-argument
wait_for_idle()waits forever, making the stated timeout path unreachable for this external-thread call. Use a finite timeout for the direct-spawn batch too.
if (!sched.wait_for_idle()) {
std::cerr << "Timed out waiting for direct-spawn batch"
<< std::endl;
std::abort();
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
@copilot please re-review only; do not make direct code modifications. |
Re-review complete. All five concerns from the original review are correctly addressed in a303254:
No issues found. The implementation is correct and complete. |
|
@copilot please re-review the current head only; do not make direct code modifications. |
Re-review of current HEAD (a303254) complete. No issues found. Full analysis:
Rejection path signal ordering —
Completed-task rejection — both paths reject before |
Description
Add direct rvalue
coro::task<T>overloads to the high-level spawn APIs. Acaller that already owns a lazy task can now transfer that root frame directly
instead of allocating a callable-wrapper coroutine and a second execution
context.
Callable overloads remain unchanged and continue to own arbitrary callables
and arguments safely. This distinction is documented because eagerly invoking
a temporary coroutine lambda can leave its frame referring to a destroyed
callable object.
Type of Change
Related Issues
Closes #1030
Changes Made
Core Changes
preserving tracking, affinity, rejection, shutdown, and frame ownership.
authority and result/destruction ordering do not depend on a wrapper.
consumed frames correctly on admission or join-state allocation failure.
API Changes
All existing callable overloads remain source-compatible.
Testing
Unit Tests
Coverage includes allocation count, result transfer, affinity, cancellation,
scheduler rejection while running, injected join-state allocation failure,
no-scheduler behavior, moved-from/empty/completed owners, and exactly-once
frame destruction.
Integration Tests
Sanitizer Testing
Test Results
Release benchmark, pinned to CPU 0, three runs:
The direct path reduced mean spawn time by 23.6% and increased mean throughput
by 29.9% in this local comparison. The benchmark is descriptive and does not
set a shared-runner timing threshold.
Checklist
Code Quality
Documentation
Testing
Compatibility
Performance
Additional Notes
The direct overload is intended for tasks returned by ordinary coroutine
functions or for tasks whose callable lifetime is otherwise known to be safe.
The callable overload remains the safe default for temporary coroutine lambdas
and arbitrary callable objects.
Reviewer Guidance
Please focus on:
failures;