Skip to content

[SLOP(claude-opus-4-8-medium)] chore: add profiling cargo profile for heaptrack leak investigation - #5314

Open
MasterPtato wants to merge 1 commit into
stack/slop-claude-opus-4-8-fix-kitchen-sink-serve-built-frontend-from-server-rymmurrkfrom
stack/slop-claude-opus-4-8-medium-chore-add-profiling-cargo-profile-for-heaptrack-leak-investigation-xsoysnqs
Open

[SLOP(claude-opus-4-8-medium)] chore: add profiling cargo profile for heaptrack leak investigation#5314
MasterPtato wants to merge 1 commit into
stack/slop-claude-opus-4-8-fix-kitchen-sink-serve-built-frontend-from-server-rymmurrkfrom
stack/slop-claude-opus-4-8-medium-chore-add-profiling-cargo-profile-for-heaptrack-leak-investigation-xsoysnqs

Conversation

@MasterPtato

@MasterPtato MasterPtato commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@MasterPtato

MasterPtato commented Jun 22, 2026

Copy link
Copy Markdown
Contributor Author

Stack for rivet-dev/rivet

Get stack: forklift get 5314
Push local edits: forklift submit
Merge when ready: forklift merge 5314

change xsoysnqs

@claude

claude Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

This PR does two things: adds a [profile.profiling] Cargo profile for heaptrack-based leak investigation, and refactors run_event_loop in napi_actor_events.rs to interleave JoinSet reaping with event dispatch so completed background tasks do not accumulate RSS over the lifetime of an actor. The fix is well-targeted: previously tasks (a JoinSet<()>) was only ever drained in drain_tasks at shutdown, so every action/HTTP/websocket dispatch spawned via spawn_reply/spawn_task retained its completed-task allocation for the full lifetime of the actor. The new tokio::select! with a join_next() arm addresses that directly, and the loop structure is otherwise correct (no busy-looping when tasks is empty due to the if !tasks.is_empty() guard, pump_registered_tasks still runs every iteration, cancel-safety of join_next/recv is preserved).

I re-verified this against the current HEAD of the PR. This looks like a rebase, and the same four issues from the prior review are still present in the diff as-is.


drain_tasks inconsistency with cancelled-task error suppression

rivetkit-typescript/packages/rivetkit-napi/src/napi_actor_events.rs:851 - The new run_event_loop join arm suppresses cancelled-task errors (if !error.is_cancelled() at line 186), but drain_tasks still error-logs every join failure including cancellations. Since abort.cancel() is called before drain_tasks runs (see run_adapter_loop), any task still in flight at that point that observes the cancellation and is later aborted will spuriously error-log here, when the equivalent situation in run_event_loop is intentionally silenced. The two reap sites should apply the same suppression.


Profiling profile comment overstates inlining suppression

Cargo.toml:677 - The comment says "keep frames un-inlined," but opt-level = 3 is inherited from release and not overridden by [profile.profiling]. codegen-units = 16 plus lto = "thin" only suppresses cross-codegen-unit inlining; opt-level = 3 still aggressively inlines within a codegen unit, so allocation sites inside hot intra-crate call chains will still collapse into their callers under heaptrack. Either add opt-level = 1 or 2 if fully un-inlined frames are the goal, or reword the comment to say it limits cross-crate inlining so it does not overpromise what this profile actually gives you.


select! without biased can delay event dispatch behind a task-reap backlog

rivetkit-typescript/packages/rivetkit-napi/src/napi_actor_events.rs:179 - tokio::select! picks pseudo-randomly among ready branches each poll. If several background tasks complete around the same time as an incoming event, the events.recv() arm is not guaranteed to win, so event dispatch can be delayed by an expected number of extra loop iterations proportional to the reap backlog. This is bounded and unlikely to cause real starvation, but adding biased; with events.recv() listed first would preserve the event-priority ordering that the original code had while still reaping tasks opportunistically.


Missing actor_id on the new join-failure error log

rivetkit-typescript/packages/rivetkit-napi/src/napi_actor_events.rs:187 - Every other error log in this file (the cleanup/disconnect paths in dispatch_event, spawn_task, drain_tasks) includes actor_id as a structured field, and CLAUDE.md calls out actor_id as a required field on runtime logs in this area. The new log is just tracing::error!(?error, "napi background task failed to join"). run_event_loop has ctx: &ActorContext in scope, so this should include actor_id = %ctx.inner().actor_id() like the rest of the file, for production attributability.


Nothing here blocks the core fix; the leak-reaping logic itself is sound. The drain_tasks inconsistency and the missing actor_id are the two worth fixing before merge; the biased and profiling-comment points are more nice-to-haves.

One more thing worth a second look: there is no test exercising the new join_next reaping path in run_event_loop itself. Existing tests call dispatch_event plus drain_tasks directly, and the one full-loop test (run_adapter_loop_resets_stale_shared_end_reason_before_wake) does not spawn any background task, so nothing currently asserts that tasks actually shrinks mid-loop rather than only at drain, which is the entire point of this change.

@railway-app

railway-app Bot commented Jun 22, 2026

Copy link
Copy Markdown

🚅 Deployed to the rivet-pr-5314 environment in rivet-frontend

Service Status Web Updated (UTC)
frontend-cloud 😴 Sleeping (View Logs) Web Aug 7, 2026 at 6:31 am
frontend-inspector 😴 Sleeping (View Logs) Web Aug 7, 2026 at 5:25 am
kitchen-sink 😴 Sleeping (View Logs) Web Aug 7, 2026 at 1:39 am
website 😴 Sleeping (View Logs) Web Aug 5, 2026 at 9:53 pm
ladle ✅ Success (View Logs) Web Jun 22, 2026 at 10:43 pm
mcp-hub ✅ Success (View Logs) Web Jun 22, 2026 at 10:42 pm

@MasterPtato
MasterPtato force-pushed the stack/slop-claude-opus-4-8-fix-kitchen-sink-serve-built-frontend-from-server-rymmurrk branch from 051f338 to 6efb5f5 Compare June 23, 2026 20:22
@MasterPtato
MasterPtato force-pushed the stack/slop-claude-opus-4-8-medium-chore-add-profiling-cargo-profile-for-heaptrack-leak-investigation-xsoysnqs branch from 4128684 to 5e48af6 Compare June 23, 2026 20:23
@railway-app
railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5314 June 23, 2026 20:32 Destroyed
@NathanFlurry NathanFlurry changed the title [SLOP(claude-opus-4-8-medium)] chore: add profiling cargo profile for heaptrack leak investigation chore: add profiling cargo profile for heaptrack leak investigation Jun 26, 2026
@MasterPtato
MasterPtato changed the base branch from stack/slop-claude-opus-4-8-fix-kitchen-sink-serve-built-frontend-from-server-rymmurrk to main August 7, 2026 00:39
@MasterPtato
MasterPtato force-pushed the stack/slop-claude-opus-4-8-medium-chore-add-profiling-cargo-profile-for-heaptrack-leak-investigation-xsoysnqs branch from d4b47f3 to c40c936 Compare August 7, 2026 01:27
@MasterPtato MasterPtato changed the title chore: add profiling cargo profile for heaptrack leak investigation [SLOP(claude-opus-4-8-medium)] chore: add profiling cargo profile for heaptrack leak investigation Aug 7, 2026
@MasterPtato
MasterPtato changed the base branch from main to stack/slop-claude-opus-4-8-fix-kitchen-sink-serve-built-frontend-from-server-rymmurrk August 7, 2026 01:27
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