Skip to content

Go: real parallel wave execution (opt-in) — execution parity with Python/Kotlin - #37

Merged
arybach merged 1 commit into
mainfrom
feat/go-parallel-wave-execution
Aug 29, 2026
Merged

Go: real parallel wave execution (opt-in) — execution parity with Python/Kotlin#37
arybach merged 1 commit into
mainfrom
feat/go-parallel-wave-execution

Conversation

@arybach

@arybach arybach commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Follow-up to the Go concurrency-metadata parity (#36). That PR made the scheduler serialize resource conflicts; the public Go runtime still executed each released wave serially. This adds actual parallel execution — the last gap to full parity with the Python and Kotlin runtimes.

What

Mirrors the proven Python _execute_wave / Kotlin thread-pool pattern: a ready wave's operator invocations (the I/O wait) run concurrently behind a join barrier, then results commit serially in deterministic node order — so world / learning / event / replay state is identical to serial; only wall-clock changes.

  • runtime.go: execute split into invoke (parallelizable) and commit/failNode (serial). New executeWave (bounded semaphore + WaitGroup). New maxConcurrency field + WithMaxConcurrency option + AGENTIC_OS_MISSION_CONCURRENCY env — default 1 (serial); parallel is opt-in, matching Python. effectiveMaxConcurrency = min(executor pool, scheduler policy), so the two ceilings are observable (schedulerConfig gains requested_concurrency + bound_by).
  • executor.go: guard InMemoryOperatorClient.seen/Calls with a mutex — the handler call runs outside the lock, so it parallelizes. Race-clean.

Tests

concurrency_exec_test.go: concurrent == serial (same terminal state, same committed nodes, same world size) + real overlap (peak parallelism > 1) + faster; default-is-serial. Full go test -race ./mission/ green, and the whole suite also passes with AGENTIC_OS_MISSION_CONCURRENCY=4 (every existing test correct under parallel execution).

Result

Go now matches Python/Kotlin on both axes: safe-concurrency scheduling (#36) and parallel wave execution (this PR), with the same serial-by-default, opt-in posture.

🤖 Generated with Claude Code

The scheduler already serialized resource conflicts, but the public Go runtime
executed each released wave SERIALLY. This adds actual parallel execution,
mirroring the proven Python `_execute_wave` / Kotlin thread-pool pattern: a
ready wave's operator invocations (the I/O wait) run concurrently behind a JOIN
BARRIER, then results commit SERIALLY in deterministic node order — so world,
learning, event and replay state are identical to serial; only wall-clock changes.

- runtime.go: split `execute` into `invoke` (parallelizable: resolveInputs +
  dispatch + operator run) and `commit` / `failNode` (serial, node order). New
  `executeWave` runs the wave with a bounded semaphore + WaitGroup. New
  `maxConcurrency` field + `WithMaxConcurrency` option + `AGENTIC_OS_MISSION_CONCURRENCY`
  env — DEFAULT 1 (serial), parallel is opt-in (matches Python). effectiveMaxConcurrency
  now = min(executor pool, scheduler policy) so the two ceilings are observable
  (schedulerConfig gains requested_concurrency + bound_by).
- executor.go: guard InMemoryOperatorClient.seen/Calls with a mutex (the handler
  call itself runs OUTSIDE the lock, so it parallelizes) — race-clean.

Tests: concurrent==serial (same terminal state, same committed nodes, same world
size) + real overlap (peak parallelism > 1) + faster; default-is-serial. Full
`go test -race ./mission/` green, and the whole suite also passes with
AGENTIC_OS_MISSION_CONCURRENCY=4 (every existing test correct under parallel exec).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@arybach
arybach merged commit 9bd3438 into main Aug 29, 2026
1 check passed
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