Skip to content

feat(interp): add Pool for multi-goroutine interpreter use#35

Merged
siyul-park merged 4 commits into
mainfrom
claude/interpreter-goroutine-concurrency-rGk01
May 22, 2026
Merged

feat(interp): add Pool for multi-goroutine interpreter use#35
siyul-park merged 4 commits into
mainfrom
claude/interpreter-goroutine-concurrency-rGk01

Conversation

@siyul-park

Copy link
Copy Markdown
Owner

Interpreter holds per-instance mutable runtime state (frames, stack, heap,
JIT buffer) and is not safe to share across goroutines. Pool lets callers
share an immutable Program while borrowing one Interpreter per goroutine
via Get/Put or Run(ctx, fn). Backed by a bounded channel with explicit
Close() so mmap'd JIT buffers are always released; Reset is called
between borrows to clear runtime state.

Interpreter holds per-instance mutable runtime state (frames, stack, heap,
JIT buffer) and is not safe to share across goroutines. Pool lets callers
share an immutable Program while borrowing one Interpreter per goroutine
via Get/Put or Run(ctx, fn). Backed by a bounded channel with explicit
Close() so mmap'd JIT buffers are always released; Reset is called
between borrows to clear runtime state.

Copy link
Copy Markdown
Owner Author

PR Review — feat(interp): add Pool for multi-goroutine interpreter use

Decision

Ready to merge

Merge Readiness Summary

This PR is merge-ready. It adds a focused, well-tested feature for concurrent VM use by enabling multiple goroutines to share a single Program and borrow Interpreter instances from a pool. The implementation follows Go concurrency best practices, has comprehensive test coverage including concurrent stress testing, and properly documents the new API and safety invariants.

Analysis

Scope Control

  • ✅ Feature is well-defined and focused (Pool only)
  • ✅ No unrelated cleanups or refactoring
  • ✅ Single commit with clear purpose

Correctness

  • ✅ Concurrency patterns are correct:
    • CAS loop properly retries on contention
    • Channel handling safe on close (ok check)
    • Mutex placement correct (protects closed flag and idle drains)
    • Atomic operations used efficiently for live count
  • ✅ Get() blocking behavior correct (respects context)
  • ✅ Put() reset and draining logic correct
  • ✅ Close() idempotent and drains idle queue properly
  • ✅ Run() defer ensures Put even after panic

Test Coverage

  • ✅ 335 lines of tests across 6 test functions
  • ✅ Covers all public methods: NewPool, Get, Put, Run, Close
  • ✅ Edge cases covered: nil handling, context cancellation, closed pool, panic recovery
  • ✅ Concurrent stress test: 16 goroutines × 50 iterations with race detection
  • ✅ Tests serve as clear API documentation (no helper indirection)

Documentation

  • ✅ Updated AGENTS.md with test guidance (go test -race ./interp)
  • ✅ Added clear section to docs/architecture.md explaining Pool's role
  • ✅ Important safety note in docs/memory-model.md: heap refs invalid after Pool.Put
  • ✅ Roadmap updated with future optimization opportunity

API Design

  • ✅ Follows naming conventions: NewPool, Get, Put, Run, Close
  • ✅ Functional options pattern for constructor (forwards to Interpreter)
  • ✅ Error handling with sentinel ErrPoolClosed
  • ✅ Clear semantics: Get() borrows, Put() resets and returns

Architecture & Compatibility

  • ✅ Additive only (no breaking changes)
  • ✅ No existing APIs modified
  • ✅ Consistent with existing Interpreter/Program design
  • ✅ Uses standard library concurrency primitives

Risk & Validation

  • ✅ All CI checks passing
  • ✅ Codecov shows 91.17% of diff covered
  • ✅ No new dependencies
  • ✅ Clean mergeable state

Readiness Checklist

  • Scope control: Pass
  • Correctness: Pass
  • Test coverage: Pass
  • Architecture consistency: Pass
  • Risk / compatibility: Pass
  • Maintainability: Pass
  • CI / validation: Pass

Final Recommendation

Merge — This is a well-executed feature with proper concurrency handling, comprehensive tests, and clear documentation.


Generated by Claude Code

- Reorder methods Run/Get/Put/Close so callers appear above callees
  (docs/coding-patterns.md §1.3).
- Split Get into isClosed/tryRecv/tryCreate/waitRecv helpers so the top
  reads as a four-step narrative at one abstraction level (§1.1).
- Regroup Pool fields into config / state / close-coordination layers
  (§2.5).
- Extract discard helper to remove the duplicated close-and-decrement
  pair in Put.
- Drop the "closes excess when idle full" subtest that fabricated an
  unreachable state via direct live counter mutation (§6.1).
- Fold the concurrent goroutines test into TestPool_Run as a subtest so
  Run has a single owning test function (§6.3).
@codecov

codecov Bot commented May 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.87342% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 53.61%. Comparing base (a7cc1b2) to head (3e9b4ca).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
interp/pool.go 89.87% 5 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #35      +/-   ##
==========================================
+ Coverage   53.31%   53.61%   +0.29%     
==========================================
  Files          53       54       +1     
  Lines        9710     9789      +79     
==========================================
+ Hits         5177     5248      +71     
- Misses       3919     3924       +5     
- Partials      614      617       +3     

☔ View full report in Codecov by Sentry.
📢 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.

claude added 2 commits May 22, 2026 11:08
Add a six-item checklist to CLAUDE.md covering the coding-patterns rules
that have been overlooked on first passes: method order, single
abstraction level, struct field layering, one test per public symbol,
tests assert behavior, and no duplicated cleanup. Reference it from the
Agent Workflow step so other agents pick up the same check.
- Rewrite coding-patterns.md §2.4 as a fixed 10-slot ordering (public
  type, private type, public/private const, public/private value,
  public/private function, public/private method) so the sequence of
  declarations is unambiguous.
- Update §2.3 so interface assertions sit in slot 6 (private values)
  rather than immediately after each type.
- Reorder interp/pool.go to match: Pool type, ErrPoolClosed, NewPool,
  public methods, private methods.
- Rename Pool helpers for conciseness: isClosed->dead, tryRecv->take,
  tryCreate->grow, waitRecv->wait, discard->drop.
- Extend CLAUDE.md self-review with the §2.4 ordering and an explicit
  preference for short intent-revealing helper names.
@siyul-park siyul-park merged commit 8fe0f1c into main May 22, 2026
5 checks passed
@siyul-park siyul-park deleted the claude/interpreter-goroutine-concurrency-rGk01 branch May 22, 2026 13:03
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.

2 participants