Skip to content

ci: add benchmarks for vm start/stop#112

Draft
austinvazquez wants to merge 1 commit intocontainerd:mainfrom
austinvazquez:add-benchmarks
Draft

ci: add benchmarks for vm start/stop#112
austinvazquez wants to merge 1 commit intocontainerd:mainfrom
austinvazquez:add-benchmarks

Conversation

@austinvazquez
Copy link
Member

No description provided.

Signed-off-by: Austin Vazquez <austin.vazquez@docker.com>
Copilot AI review requested due to automatic review settings March 13, 2026 21:36
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds CI-run benchmarks to measure VM lifecycle performance (start, shutdown, and full start/stop) across supported VM backends, and publishes results in the workflow summary.

Changes:

  • Introduces VM lifecycle benchmarks in integration/vm_test.go.
  • Refactors integration test backend selection to a shared vmBackends list.
  • Adds a new GitHub Actions job to run and publish benchmark results.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 11 comments.

File Description
integration/vm_test.go Adds three benchmarks for VM start/shutdown/start-stop across backends.
integration/main_test.go Extracts VM backend configuration into a shared vmBackends variable.
.github/workflows/ci.yml Adds a benchmarks job to run go test -bench=... and publish output to the step summary.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +78 to +96
for b.Loop() {
td := b.TempDir()
// Resolve symlinks so the VM sees a canonical path.
resolvedTd, err := filepath.EvalSymlinks(td)
if err != nil {
b.Fatal("failed to resolve temp dir:", err)
}
if err := os.Chdir(resolvedTd); err != nil {
b.Fatal("failed to chdir:", err)
}

instance, err := backend.vmm.NewInstance(b.Context(), resolvedTd)
if err != nil {
b.Fatal("failed to create VM instance:", err)
}

b.StartTimer()
if err := instance.Start(b.Context()); err != nil {
b.Fatal("failed to start VM:", err)
if err != nil {
b.Fatal("failed to resolve temp dir:", err)
}
if err := os.Chdir(resolvedTd); err != nil {
}
b.StopTimer()

instance.Shutdown(b.Context())
Comment on lines +111 to +118
td := b.TempDir()
resolvedTd, err := filepath.EvalSymlinks(td)
if err != nil {
b.Fatal("failed to resolve temp dir:", err)
}
if err := os.Chdir(resolvedTd); err != nil {
b.Fatal("failed to chdir:", err)
}
Comment on lines +144 to +151
td := b.TempDir()
resolvedTd, err := filepath.EvalSymlinks(td)
if err != nil {
b.Fatal("failed to resolve temp dir:", err)
}
if err := os.Chdir(resolvedTd); err != nil {
b.Fatal("failed to chdir:", err)
}
Comment on lines +236 to +305
benchmarks:
name: Benchmarks
needs: [setup, build-kernels]
if: |
always() &&
(needs.build-kernels.result == 'success' || needs.build-kernels.result == 'skipped')
runs-on: ${{ matrix.os }}
timeout-minutes: 20

strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
arch: x86_64

steps:
- name: Enable KVM group perms
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
sudo usermod -aG kvm $USER

- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Calculate kernel cache key
id: cache-key
run: |
CONFIG_FILE="kernel/config-${{ needs.setup.outputs.kernel-version }}-${{ matrix.arch }}"

if [ ! -f "$CONFIG_FILE" ]; then
echo "Error: Kernel config file $CONFIG_FILE not found"
exit 1
fi

CONFIG_HASH=$(sha256sum "$CONFIG_FILE" | cut -d' ' -f1)
PATCHES_HASH=$(find kernel/patches -type f -name "*.patch" -exec sha256sum {} \; | sort | sha256sum | cut -d' ' -f1)
CACHE_KEY="kernel-${{ needs.setup.outputs.kernel-version }}-${{ matrix.arch }}-${CONFIG_HASH:0:8}-${PATCHES_HASH:0:8}"

echo "cache-key=${CACHE_KEY}" >> $GITHUB_OUTPUT

- name: Restore cached kernel
id: cache-kernel
uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
path: _output/nerdbox-kernel-${{ matrix.arch }}
key: ${{ steps.cache-key.outputs.cache-key }}

- name: Verify kernel from cache
run: |
if [ "${{ steps.cache-kernel.outputs.cache-hit }}" = "true" ]; then
echo "✅ Kernel restored from cache"
else
echo "❌ Kernel not in cache - this should not happen after build-kernels"
exit 1
fi

- uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1

- name: Build remaining artifacts (initrd and shim)
run: docker buildx bake host-binaries guest-binaries

- name: Add _output to PATH
run: echo "$(pwd)/_output" >> $GITHUB_PATH

- uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
go-version-file: '.github/.tool-versions'

Comment on lines +78 to +82
for b.Loop() {
td := b.TempDir()
// Resolve symlinks so the VM sees a canonical path.
resolvedTd, err := filepath.EvalSymlinks(td)
if err != nil {
Comment on lines +73 to +92
// BenchmarkVMStart measures the time to create and start a VM instance until
// its TTRPC endpoint is ready to serve requests.
func BenchmarkVMStart(b *testing.B) {
for _, backend := range vmBackends {
b.Run(backend.name, func(b *testing.B) {
for b.Loop() {
td := b.TempDir()
// Resolve symlinks so the VM sees a canonical path.
resolvedTd, err := filepath.EvalSymlinks(td)
if err != nil {
b.Fatal("failed to resolve temp dir:", err)
}
if err := os.Chdir(resolvedTd); err != nil {
b.Fatal("failed to chdir:", err)
}

instance, err := backend.vmm.NewInstance(b.Context(), resolvedTd)
if err != nil {
b.Fatal("failed to create VM instance:", err)
}
Comment on lines +110 to +130
for b.Loop() {
td := b.TempDir()
resolvedTd, err := filepath.EvalSymlinks(td)
if err != nil {
b.Fatal("failed to resolve temp dir:", err)
}
if err := os.Chdir(resolvedTd); err != nil {
b.Fatal("failed to chdir:", err)
}

instance, err := backend.vmm.NewInstance(b.Context(), resolvedTd)
if err != nil {
b.Fatal("failed to create VM instance:", err)
}
if err := instance.Start(b.Context()); err != nil {
b.Fatal("failed to start VM:", err)
}

b.StartTimer()
if err := instance.Shutdown(b.Context()); err != nil {
b.Fatal("failed to shut down VM:", err)
Comment on lines +143 to +148
for b.Loop() {
td := b.TempDir()
resolvedTd, err := filepath.EvalSymlinks(td)
if err != nil {
b.Fatal("failed to resolve temp dir:", err)
}
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