Skip to content

perf(nvsnap): coalesce cuda-checkpoint restore+unlock (Lever B)#263

Merged
balajinvda merged 4 commits into
mainfrom
nvsnap-restore-leverb
Jul 22, 2026
Merged

perf(nvsnap): coalesce cuda-checkpoint restore+unlock (Lever B)#263
balajinvda merged 4 commits into
mainfrom
nvsnap-restore-leverb

Conversation

@balajinvda

@balajinvda balajinvda commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Why

Two related pieces of criu-v2 GPU checkpoint/restore hardening.

  1. Second restore-speedup lever, on top of Lever A (huge-page CRIU restore, merged in feat(nvsnap): enable UV_USE_IO_URING after CRIU SQ-array restore fix #225). Each cuda-checkpoint invocation pays a fixed ~2.7s cuInit driver-attach (measured: 6 successive --get-state calls on a running process, all ~2.7s, so it is driver attach, not a wait). On the common restore path the CRIU cuda plugin spawns cuda-checkpoint separately for restore and for unlock, paying that cuInit twice per GPU pid.
  2. A correctness fix so GPU checkpoint works on containers whose glibc is newer than the CRIU bundle's (sglang cu129 and other recent images), which previously failed the dump.

What changed (Lever B)

  • CRIU fork (1e926fa4d): the cuda plugin coalesces restore + unlock into a single combined resume invocation when both apply (the common criu restore case), falling back to the individual actions for the restore-only (locked) and unlock-only cases. Same driver operations, same order, one fewer process spawn per pid.
  • docker/agent/nvsnap-cuda-checkpoint.c: adds the resume action (restore then unlock in one process, one cuInit).

The win scales with the GPU pid count, so it compounds on multi-process and multi-pid NIM workloads.

What changed (newer-glibc fix)

The criu-v2 engine ran criu with LD_LIBRARY_PATH=/criu-bundle/lib so criu could resolve its own transitive deps (libnftables -> libmnl; DT_RUNPATH on the criu binary is not inherited by its libraries). That env var is also inherited by cuda-checkpoint, which criu spawns per GPU pid. On a container whose glibc is newer than the bundle's (e.g. sglang v0.5.x-cu129, glibc 2.36) cuda-checkpoint aborts with GLIBC_2.36 not found, silently disabling the CUDA plugin so GPU memory is never released and the dump fails on an un-released device mapping. vllm images (glibc <= 2.35) were unaffected, which is why this only surfaced on sglang.

Fix (packaging only, no CRIU fork change): make the bundle self-contained the standard way.

  • docker/agent/Dockerfile.base: set RPATH=$ORIGIN on each bundled library (and $ORIGIN/../lib on plugins) so the loader resolves siblings without LD_LIBRARY_PATH.
  • internal/agent/checkpoint_v2.go, restore_v2.go: drop LD_LIBRARY_PATH from the criu-v2 dump/restore env entirely, so cuda-checkpoint inherits a clean env and resolves libc/libm from the target container.

Versions

Pins CRIU ref 1e926fa4d; bumps base v0.0.14 / app v0.2.25 (+ manifest tag sync).

Restore speedup: cumulative (agent restore, single GPU)

Workload Checkpoint Baseline (v0.2.20) + A (v0.2.21) + A+B (v0.2.22) Total
vllm-small 3.2G 44.3s 32.2s 25.8s -42%
vllm-8b 18G 58.9s 38.5s 32.4s -45%
e5-mistral 15G 84.0s 40.8s 36.6s -56%
vllm-qwen32b 64G 77.4s 48.5s 44.3s -43%

Lever B contributes a consistent -4 to -6s (one cuInit per pid x 2 pids). No regression: every workload improved at every step.

Testing

  • criu-v2 single-GPU regression 5/5 PASS on the A+B build (vllm-small, vllm-8b, e5-mistral, vllm-qwen32b, plus vllm-mp multi-process). Post-restore inference verified. The coalesce is correctness-neutral: same driver operations in the same order, one fewer spawn.
  • newer-glibc fix validated on aws-dev1: vllm-small criu-v2 e2e PASS (RPATH-hardened bundle, no regression) and gemma-4-31B on sglang v0.5.15.post1-cu129 criu-v2 e2e PASS (checkpoint 3m16s/36G, restore-pod-ready 1m12s, post-restore inference OK). Before the fix the sglang dump failed with the CUDA plugin disabled by the glibc mismatch. Adds a gemma-sglang test-e2e workload as the regression test.

Customer Release Notes

criu-v2 GPU restore is a further several seconds faster per workload (fewer redundant CUDA driver attaches), on top of the Lever A huge-page speedup; cumulative single-GPU restore improvement is now -42% to -56%. GPU checkpoint now also works on container images that ship a newer glibc than the CRIU bundle (e.g. recent sglang builds), which previously failed to checkpoint.

Notes

The newer-glibc fix is general to any workload whose container glibc is newer than the CRIU bundle's, not only sglang. Recent NIM images (e.g. whisper-large-v3) are also newer-glibc and would hit the same cuda-checkpoint glibc abort if run through criu-v2. Whisper and other Riva/Triton NIM backends currently route to the rootfs capture path (capture-path matrix; a host-pinned-memory constraint unrelated to glibc), so their routing is unchanged here -- sglang is the criu-v2 case validated in this PR.

References

Relates to #71

Summary by CodeRabbit

  • New Features

    • Added Gemma SGLang single-GPU checkpoint/restore workloads (including a dedicated restore manifest).
    • Added a combined resume operation to streamline CUDA restore workflows (restore+unlock as one step).
  • Improvements

    • Updated the NVSNAP agent/runtime version used by deployment and benchmark workloads.
    • Enhanced checkpoint/restore library packaging to improve compatibility across container environments.
  • Documentation

    • Refreshed benchmark guidance and timing results for faster CRIU-v2 restore (“Levers A+B”).
  • Tests

    • Expanded end-to-end test coverage to include the Gemma SGLang single-GPU workload.

Each cuda-checkpoint spawn pays a fixed ~2.7s cuInit driver-attach. On the
common restore path a process needs both a restore and an unlock, previously
two separate spawns. The cuda plugin now issues a single combined "resume"
action (restore then unlock in one process), and nvsnap-cuda-checkpoint.c
gains that action. Same driver operations, same order, one fewer spawn per
GPU pid; the win scales with pid count.

Pins CRIU ref to 1e926fa4d, bumps base v0.0.12 / app v0.2.22.

Measured on aws-dev1 (H100, criu-v2), agent restore, on top of Lever A:
- vllm-small 32.2 -> 25.8s, vllm-8b 38.5 -> 32.4s,
  e5-mistral 40.8 -> 36.6s, vllm-qwen32b 48.5 -> 44.3s.
Cumulative vs pre-optimization baseline: -42% to -56%. 5/5 single-GPU e2e
PASS. Design + full table in docs/proposals/single-gpu-restore-speedup.md
and docs/BENCHMARK.md.

Co-Authored-By: Balaji Ganesan <bganesan@nvidia.com>
@balajinvda
balajinvda requested a review from a team as a code owner July 20, 2026 15:10
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 46d66b4f-0f84-4b83-8039-a83eb250a66f

📥 Commits

Reviewing files that changed from the base of the PR and between 63fd39d and 8968cee.

📒 Files selected for processing (3)
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/e5-mistral-replay.yaml
  • src/compute-plane-services/nvsnap/docs/proposals/single-gpu-restore-speedup.md
  • src/compute-plane-services/nvsnap/scripts/versions.sh
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/e5-mistral-replay.yaml
  • src/compute-plane-services/nvsnap/docs/proposals/single-gpu-restore-speedup.md
  • src/compute-plane-services/nvsnap/scripts/versions.sh

📝 Walkthrough

Walkthrough

NVSNAP v0.2.26 adds CUDA resume handling, embedded CRIU library resolution, updated agent and CRIU references, Gemma SGLang workload manifests and end-to-end support, and revised restore benchmark documentation.

Changes

NVSNAP v0.2.26 release

Layer / File(s) Summary
CUDA resume and CRIU runtime changes
src/compute-plane-services/nvsnap/docker/agent/nvsnap-cuda-checkpoint.c, src/compute-plane-services/nvsnap/docker/agent/Dockerfile.base, src/compute-plane-services/nvsnap/internal/agent/*.go
Adds resume dispatching to restore followed by unlock, packages CRIU libraries with RPATH, and removes CRIU bundle LD_LIBRARY_PATH overrides.
Gemma SGLang workload integration
src/compute-plane-services/nvsnap/deploy/k8s/workloads/gemma-sglang*.yaml, src/compute-plane-services/nvsnap/scripts/test-e2e.sh
Adds workload and restore Pod manifests and registers gemma-sglang in end-to-end workload selection and validation.
Release references and agent image rollout
src/compute-plane-services/nvsnap/scripts/versions.sh, src/compute-plane-services/nvsnap/deploy/k8s/agent-daemonset*.yaml, src/compute-plane-services/nvsnap/deploy/k8s/benchmarks/*, src/compute-plane-services/nvsnap/deploy/k8s/workloads/*
Updates base/app versions, the pinned CRIU revision, and NVSNAP agent image references to v0.2.26.
Restore benchmark documentation
src/compute-plane-services/nvsnap/docs/BENCHMARK.md, src/compute-plane-services/nvsnap/docs/proposals/single-gpu-restore-speedup.md
Documents the resume optimization, updated restore measurements, and remaining Lever B work.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI as cuda-checkpoint CLI
  participant Main as main()
  participant Resume as do_resume(pid)
  participant Restore as do_restore(pid)
  participant Unlock as do_unlock(pid)
  CLI->>Main: --action resume
  Main->>Resume: dispatch pid
  Resume->>Restore: restore pid
  Restore-->>Resume: status
  Resume->>Unlock: unlock pid on success
  Unlock-->>CLI: return status
Loading

Suggested reviewers: famousdirector

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly names the main change: coalescing restore+unlock into Lever B for nvsnap.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch nvsnap-restore-leverb

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

🛡️ CodeQL Analysis

🚨 Found 2 issue(s)

Severity Breakdown:

  • 🔴 Errors: 0
  • 🟡 Warnings: 0
  • 🔵 Notes: 0
📋 Top Issues

🔗 View full details in Security tab

🕐 Last updated: 2026-07-20 15:13:27 UTC | Commit: cef32fc

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/compute-plane-services/nvsnap/docker/agent/nvsnap-cuda-checkpoint.c (1)

1-2: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Restore the SPDX header.

Removing the file’s copyright and license block weakens automated attribution and license compliance for this distributable source. Restore the original header unchanged.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/compute-plane-services/nvsnap/docker/agent/nvsnap-cuda-checkpoint.c`
around lines 1 - 2, Restore the original SPDX copyright and license header at
the beginning of nvsnap-cuda-checkpoint.c, preserving it unchanged before the
existing file description comment.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/compute-plane-services/nvsnap/deploy/k8s/workloads/e5-mistral-replay.yaml`:
- Line 49: Update the surrounding comments in the e5-mistral-replay manifest to
reference nvsnap-agent v0.2.22 and its current bundle-staging path, replacing
all stale v0.0.20 guidance while leaving the image configuration unchanged.

In
`@src/compute-plane-services/nvsnap/docs/proposals/single-gpu-restore-speedup.md`:
- Around line 96-118: Synchronize all other Lever B status and phasing
references with the proposal section: mark the combined resume invocation as
completed and shipped, while identifying get-restore-tid elimination as
remaining medium work and per-pid context parallelization as deferred hard work.
Update only the stale statements that describe Lever B as wholly unimplemented
or planned, preserving the existing distinction and scope.

In `@src/compute-plane-services/nvsnap/scripts/versions.sh`:
- Around line 45-46: Update the comment adjacent to NVSNAP_BASE_VERSION and
NVSNAP_APP_VERSION to accurately describe their current v0.0.12 and v0.2.22
defaults, replacing the outdated v0.0.1 core-image baseline statement.

---

Outside diff comments:
In `@src/compute-plane-services/nvsnap/docker/agent/nvsnap-cuda-checkpoint.c`:
- Around line 1-2: Restore the original SPDX copyright and license header at the
beginning of nvsnap-cuda-checkpoint.c, preserving it unchanged before the
existing file description comment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: e61901bb-97f6-4d71-9aff-0e493796008a

📥 Commits

Reviewing files that changed from the base of the PR and between 9ea0b4b and cef32fc.

📒 Files selected for processing (18)
  • src/compute-plane-services/nvsnap/deploy/k8s/agent-daemonset-crio.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/agent-daemonset.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/benchmarks/gemma-4-31b-nim-restore.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/benchmarks/gemma-4-31b-nim.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/benchmarks/whisper-large-v3-restore.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/e5-mistral-replay.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/nim-llama-8b-restore.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/nim-llama-8b.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/sglang-8b-restore.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/sglang-8b.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/sglang-small-restore.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/sglang-small.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/trtllm-small-restore.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/trtllm-small.yaml
  • src/compute-plane-services/nvsnap/docker/agent/nvsnap-cuda-checkpoint.c
  • src/compute-plane-services/nvsnap/docs/BENCHMARK.md
  • src/compute-plane-services/nvsnap/docs/proposals/single-gpu-restore-speedup.md
  • src/compute-plane-services/nvsnap/scripts/versions.sh

Comment thread src/compute-plane-services/nvsnap/deploy/k8s/workloads/e5-mistral-replay.yaml Outdated
Comment thread src/compute-plane-services/nvsnap/scripts/versions.sh Outdated
…uses the container glibc

The criu-v2 engine ran criu with LD_LIBRARY_PATH=/criu-bundle/lib to
resolve criu's own transitive deps (libnftables -> libmnl), since
DT_RUNPATH on the criu binary is not inherited by its libraries. But that
env var is also inherited by cuda-checkpoint, which criu spawns per GPU
process. On a container whose glibc is newer than the bundle's (e.g.
sglang v0.5.x-cu129, glibc 2.36) cuda-checkpoint aborts with "GLIBC_2.36
not found", which silently disables the CUDA plugin -- GPU memory is
never released and the dump then fails on an un-released device mapping.

Make the bundle self-contained the standard way: set RPATH=$ORIGIN on
each bundled library so the loader finds siblings without LD_LIBRARY_PATH,
then drop LD_LIBRARY_PATH from the criu-v2 dump and restore env entirely.
cuda-checkpoint now inherits a clean env and resolves libc/libm from the
target container. No CRIU fork change is needed (the fix is in packaging).

Validated on aws-dev1: vllm-small criu-v2 e2e PASS (no regression) and
gemma-4-31B sglang cu129 criu-v2 e2e PASS (checkpoint 3m16s/36G, restore
1m12s, post-restore inference OK). Adds a gemma-sglang test-e2e workload
as the regression test.

Co-Authored-By: Balaji Ganesan <bganesan@nvidia.com>

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/compute-plane-services/nvsnap/deploy/k8s/workloads/gemma-sglang.yaml`:
- Around line 62-66: Remove the HF_TOKEN environment variable injection from the
checkpointed sglang.launch_server workload. Move gated-model authentication and
downloading into a separate pre-checkpoint phase that can access the hf-token
secret, then ensure the server starts from the cached model without inheriting
HF_TOKEN.
- Around line 25-82: Harden the sglang container by disabling automatic
service-account token mounting at the pod spec level and removing the
securityContext.privileged setting from the container. Preserve the existing
SGLang launch configuration and only retain privileged execution if a concrete
capability required by this workload is identified.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9387d9b0-7343-4a25-9796-1f21b0acbf9b

📥 Commits

Reviewing files that changed from the base of the PR and between cef32fc and 4996285.

📒 Files selected for processing (21)
  • src/compute-plane-services/nvsnap/deploy/k8s/agent-daemonset-crio.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/agent-daemonset.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/benchmarks/gemma-4-31b-nim-restore.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/benchmarks/gemma-4-31b-nim.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/benchmarks/whisper-large-v3-restore.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/e5-mistral-replay.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/gemma-sglang-restore.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/gemma-sglang.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/nim-llama-8b-restore.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/nim-llama-8b.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/sglang-8b-restore.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/sglang-8b.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/sglang-small-restore.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/sglang-small.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/trtllm-small-restore.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/trtllm-small.yaml
  • src/compute-plane-services/nvsnap/docker/agent/Dockerfile.base
  • src/compute-plane-services/nvsnap/internal/agent/checkpoint_v2.go
  • src/compute-plane-services/nvsnap/internal/agent/restore_v2.go
  • src/compute-plane-services/nvsnap/scripts/test-e2e.sh
  • src/compute-plane-services/nvsnap/scripts/versions.sh
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/nim-llama-8b.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/e5-mistral-replay.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/trtllm-small.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/trtllm-small-restore.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/benchmarks/whisper-large-v3-restore.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/sglang-small-restore.yaml
  • src/compute-plane-services/nvsnap/deploy/k8s/workloads/sglang-8b.yaml

balaji-g and others added 2 commits July 20, 2026 21:34
…ore+unlock

Harden the Lever B resume coalesce so the CRIU cuda plugin behaves
correctly against a cuda-checkpoint build without the combined `resume`
action: detect support once via the help output and fall back to
separate restore then unlock when unavailable. Also fixes a latent bug
where the pre-resume else-if chain would have skipped unlock for a
process needing both restore and unlock.

Bumps CRIU ref to 31d90a8a8, base v0.0.15 / app v0.2.26 (+ manifest tag
sync). Validated on aws-dev1: vllm-small (resume path exercised) and
gemma-4-31B sglang cu129 criu-v2 e2e both PASS.

Co-Authored-By: Balaji Ganesan <bganesan@nvidia.com>
- versions.sh: baseline comment reflected the historical v0.0.1 reset as if
  current; reword to say bumped-from-there.
- e5-mistral-replay.yaml: init-container comment hardcoded a stale v0.0.20
  agent; point at the synced nvsnap-agent tag instead.
- single-gpu-restore-speedup.md: status/phasing said Lever B was unimplemented
  while the body describes the resume coalesce as shipped; sync both.

Co-Authored-By: Balaji Ganesan <bganesan@nvidia.com>
@balajinvda
balajinvda added this pull request to the merge queue Jul 22, 2026
Merged via the queue into main with commit 583463b Jul 22, 2026
16 checks passed
@balajinvda
balajinvda deleted the nvsnap-restore-leverb branch July 22, 2026 14:08
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.

3 participants