From 026737d4fc4212a4622156793873d188157ea0ea Mon Sep 17 00:00:00 2001 From: danbugs Date: Thu, 21 May 2026 21:51:02 +0000 Subject: [PATCH 1/2] reduce default memory from 512Mi to 64Mi every example already specifies its own --memory value in its Justfile, so nothing depends on the CLI default. 64Mi comfortably covers the lightweight examples (helloworld-c needs 4Mi, rust/go/dotnet/shell need 16Mi) while heavier workloads (python 512Mi, powershell 1Gi) continue to set their own. Signed-off-by: danbugs --- host/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/src/main.rs b/host/src/main.rs index f5437ce..88bf73d 100644 --- a/host/src/main.rs +++ b/host/src/main.rs @@ -27,8 +27,8 @@ struct Args { #[arg(long)] initrd: Option, - /// Memory allocation (e.g., 256Mi, 512Mi, 1Gi) - #[arg(long, short = 'm', default_value = "512Mi")] + /// Memory allocation (e.g., 64Mi, 256Mi, 1Gi) + #[arg(long, short = 'm', default_value = "64Mi")] memory: String, /// Stack size (e.g., 8Mi) From bb82d7d6575baac1e678bf4874f82c7f4c176070 Mon Sep 17 00:00:00 2001 From: danbugs Date: Thu, 21 May 2026 22:33:29 +0000 Subject: [PATCH 2/2] set example memory to measured minimums, derive CI values from Justfiles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit binary-searched the minimum --memory each example needs to produce its expected output: helloworld-c: 2Mi rust: 16Mi go: 16Mi shell: 16Mi dotnet: 16Mi dotnet-nativeaot: 8Mi hostfs-posix-c: 2Mi hostfs-posix-py: 512Mi python: 512Mi python-tools: 512Mi nodejs: 512Mi powershell: 1Gi networking-py: 32Mi python-agent: 1Gi update each example's Justfile to use its measured minimum, and have CI read the memory value from the Justfile instead of hardcoding it in the workflow matrix. this makes the Justfile the single source of truth. also fixes two under-provisioned examples that were silently relying on headroom: hostfs-posix-py (was 96Mi, needs 512Mi) and python-tools (was 96Mi, needs 512Mi). lower the CLI default from 512Mi to 32Mi — covers every lightweight example with headroom while giving an honest signal that heavy runtimes (python, nodejs, powershell) need explicit --memory. Signed-off-by: danbugs --- .github/workflows/test-examples.yml | 67 +++++++++++++---------------- examples/dotnet-nativeaot/Justfile | 2 +- examples/helloworld-c/Justfile | 2 +- examples/hostfs-posix-c/Justfile | 2 +- examples/hostfs-posix-py/Justfile | 2 +- examples/networking-py/Justfile | 2 +- examples/python-tools/Justfile | 2 +- host/src/main.rs | 4 +- 8 files changed, 38 insertions(+), 45 deletions(-) diff --git a/.github/workflows/test-examples.yml b/.github/workflows/test-examples.yml index 94793fe..48614f5 100644 --- a/.github/workflows/test-examples.yml +++ b/.github/workflows/test-examples.yml @@ -153,6 +153,9 @@ jobs: # Full matrix — every example actually runs and its expected output is # greped from the guest console. This is the real regression gate; # build-example above only catches link-time errors. + # + # Memory values are read from each example's Justfile at runtime + # (the `memory` variable), so the matrix only carries args/expect. runtime-test: runs-on: ubuntu-latest needs: build-example @@ -165,76 +168,59 @@ jobs: matrix: include: - example: helloworld-c - memory: "4Mi" args: "" expect: "Hello from C on Hyperlight" - example: rust - memory: "16Mi" args: "" expect: "Hello from Rust on Hyperlight" - example: go - memory: "96Mi" args: "" expect: "Hello from Go on Hyperlight" - example: shell - memory: "16Mi" args: "-- /demo.sh" expect: "Hello from Shell on Hyperlight" - example: python - memory: "512Mi" args: "-- /hello.py" expect: "Hello from Python on Hyperlight" - example: python-tools - memory: "1Gi" args: "--enable-tools -- /test_tools.py" expect: "Tool returned" - example: nodejs - memory: "512Mi" args: "-- /app/hello.js" expect: "Hello from Node.js on Hyperlight" - example: dotnet - memory: "512Mi" args: "" expect: "Hello, World! From .NET on Hyperlight" - example: dotnet-nativeaot - memory: "512Mi" args: "" expect: "Hello, World! From .NET NativeAOT on Hyperlight" - example: hostfs-posix-c - memory: "16Mi" args: "" expect: "done\\." needs_mount: true - example: hostfs-posix-py - memory: "512Mi" args: "-- /hostfs_demo.py" expect: "done\\." needs_mount: true - example: multifn-c - memory: "4Mi" args: "" expect: "RUN: world" driver: multifn-test - example: python-agent - memory: "1Gi" args: "-- /agent.py" expect: "done\\." needs_mount: true - example: python-agent-driver - memory: "2Gi" args: "" expect: "hello from driver" driver: pydriver-run - example: powershell - memory: "1Gi" args: "-- -NoProfile -File /scripts/hello.ps1" expect: "Hello, World! From PowerShell on Hyperlight" - example: networking-py - memory: "512Mi" args: "--net -- /urllib_get.py" expect: "SUCCESS: urllib GET worked!" - example: networking-py - memory: "512Mi" args: "--port 8080 -- /echo_server_test.py" expect: "SUCCESS: bind\\+listen on port 8080 allowed" steps: @@ -340,6 +326,11 @@ jobs: ls -la .unikraft/build/ *.cpio 2>&1 | head -40 || true exit 1 fi + # Read memory from the example's Justfile (single source of truth). + memory=$(grep '^memory' Justfile | sed 's/memory.*:= *"//' | sed 's/".*//') + if [ -z "$memory" ]; then + echo "::notice::No memory variable in Justfile, using binary default" + fi expect='${{ matrix.expect }}' mount_args="" if [ "${{ matrix.needs_mount }}" = "true" ]; then @@ -355,7 +346,11 @@ jobs: cmd=(timeout 120 /home/runner/work/hyperlight-unikraft/hyperlight-unikraft/host/target/release/pydriver-run "$kernel" "$cpio" /tmp/tiny.py) ;; *) - cmd=(timeout 120 hyperlight-unikraft -q -m "${{ matrix.memory }}" "$kernel" --initrd "$cpio" $mount_args ${{ matrix.args }}) + mem_args="" + if [ -n "$memory" ]; then + mem_args="-m $memory" + fi + cmd=(timeout 120 hyperlight-unikraft -q $mem_args "$kernel" --initrd "$cpio" $mount_args ${{ matrix.args }}) ;; esac set +e @@ -490,6 +485,8 @@ jobs: # The only difference is we can't build the images on Windows (no # kraft-hyperlight + no Linux docker), so we download them from the # package-images-for-windows job. + # + # Memory values are read from each example's Justfile at runtime. runtime-test-windows: runs-on: windows-latest needs: package-images-for-windows @@ -502,76 +499,59 @@ jobs: matrix: include: - example: helloworld-c - memory: "4Mi" args: "" expect: "Hello from C on Hyperlight" - example: rust - memory: "16Mi" args: "" expect: "Hello from Rust on Hyperlight" - example: go - memory: "96Mi" args: "" expect: "Hello from Go on Hyperlight" - example: shell - memory: "16Mi" args: "-- /demo.sh" expect: "Hello from Shell on Hyperlight" - example: python - memory: "512Mi" args: "-- /hello.py" expect: "Hello from Python on Hyperlight" - example: python-tools - memory: "1Gi" args: "--enable-tools -- /test_tools.py" expect: "Tool returned" - example: nodejs - memory: "512Mi" args: "-- /app/hello.js" expect: "Hello from Node.js on Hyperlight" - example: dotnet - memory: "512Mi" args: "" expect: "Hello, World! From .NET on Hyperlight" - example: dotnet-nativeaot - memory: "512Mi" args: "" expect: "Hello, World! From .NET NativeAOT on Hyperlight" - example: hostfs-posix-c - memory: "16Mi" args: "" expect: "done\\." needs_mount: true - example: hostfs-posix-py - memory: "512Mi" args: "-- /hostfs_demo.py" expect: "done\\." needs_mount: true - example: multifn-c - memory: "4Mi" args: "" expect: "RUN: world" driver: multifn-test - example: python-agent - memory: "1Gi" args: "-- /agent.py" expect: "done\\." needs_mount: true - example: python-agent-driver - memory: "2Gi" args: "" expect: "hello from driver" driver: pydriver-run - example: powershell - memory: "1Gi" args: "-- -NoProfile -File /scripts/hello.ps1" expect: "Hello, World! From PowerShell on Hyperlight" - example: networking-py - memory: "512Mi" args: "--net -- /urllib_get.py" expect: "SUCCESS: urllib GET worked!" - example: networking-py - memory: "512Mi" args: "--port 8080 -- /echo_server_test.py" expect: "SUCCESS: bind\\+listen on port 8080 allowed" steps: @@ -614,10 +594,19 @@ jobs: $cpio = (Resolve-Path "image/initrd.cpio").Path $expect = '${{ matrix.expect }}' $driver = '${{ matrix.driver }}' - $memory = '${{ matrix.memory }}' $runArgs = '${{ matrix.args }}' $needsMount = '${{ matrix.needs_mount }}' + # Read memory from the example's Justfile (single source of truth). + $memory = '' + $justfile = "examples/${{ matrix.example }}/Justfile" + if (Test-Path $justfile) { + $memLine = Get-Content $justfile | Where-Object { $_ -match '^\s*memory\s*:=' } + if ($memLine -match '"([^"]+)"') { + $memory = $Matches[1] + } + } + $mountArgs = @() if ($needsMount -eq 'true') { $mountDir = Join-Path $env:RUNNER_TEMP ('hostfs-' + '${{ matrix.example }}') @@ -649,7 +638,11 @@ jobs: if ($runArgs -ne '') { $argList = $runArgs.Split(' ') | Where-Object { $_ -ne '' } } - $out = & hyperlight-unikraft -q -m $memory ` + $memArgs = @() + if ($memory -ne '') { + $memArgs = @('-m', $memory) + } + $out = & hyperlight-unikraft -q @memArgs ` $kernel --initrd $cpio @mountArgs @argList 2>&1 $rc = $LASTEXITCODE } diff --git a/examples/dotnet-nativeaot/Justfile b/examples/dotnet-nativeaot/Justfile index 4c2dc0b..6c2f8df 100644 --- a/examples/dotnet-nativeaot/Justfile +++ b/examples/dotnet-nativeaot/Justfile @@ -11,7 +11,7 @@ export DOCKER_BUILDKIT := "0" kernel := ".unikraft/build/dotnet-nativeaot-hyperlight_hyperlight-x86_64" initrd := "hello-initrd.cpio" -memory := "16Mi" +memory := "8Mi" image := "dotnet-nativeaot-hyperlight" ghcr_kernel := "ghcr.io/hyperlight-dev/hyperlight-unikraft/dotnet-nativeaot-kernel:latest" diff --git a/examples/helloworld-c/Justfile b/examples/helloworld-c/Justfile index 33ce0f6..55a9994 100644 --- a/examples/helloworld-c/Justfile +++ b/examples/helloworld-c/Justfile @@ -11,7 +11,7 @@ export DOCKER_BUILDKIT := "0" kernel := ".unikraft/build/helloworld-hyperlight_hyperlight-x86_64" initrd := "hello-initrd.cpio" -memory := "4Mi" +memory := "2Mi" image := "helloworld-c-hyperlight" ghcr_kernel := "ghcr.io/hyperlight-dev/hyperlight-unikraft/helloworld-c-kernel:latest" diff --git a/examples/hostfs-posix-c/Justfile b/examples/hostfs-posix-c/Justfile index 817ac44..0b6c2df 100644 --- a/examples/hostfs-posix-c/Justfile +++ b/examples/hostfs-posix-c/Justfile @@ -8,7 +8,7 @@ export DOCKER_BUILDKIT := "0" kernel := ".unikraft/build/hostfs-posix-c-hyperlight_hyperlight-x86_64" initrd := "hostfs-posix-c-initrd.cpio" -memory := "16Mi" +memory := "2Mi" image := "hostfs-posix-c-hyperlight" ghcr_kernel := "ghcr.io/hyperlight-dev/hyperlight-unikraft/hostfs-posix-c-kernel:latest" mount_dir := "./work" diff --git a/examples/hostfs-posix-py/Justfile b/examples/hostfs-posix-py/Justfile index 5c3e848..4d4c3ef 100644 --- a/examples/hostfs-posix-py/Justfile +++ b/examples/hostfs-posix-py/Justfile @@ -8,7 +8,7 @@ export DOCKER_BUILDKIT := "0" kernel := ".unikraft/build/hostfs-posix-py-hyperlight_hyperlight-x86_64" initrd := "hostfs-posix-py-initrd.cpio" -memory := "96Mi" +memory := "512Mi" image := "hostfs-posix-py-hyperlight" ghcr_kernel := "ghcr.io/hyperlight-dev/hyperlight-unikraft/hostfs-posix-py-kernel:latest" mount_dir := "./work" diff --git a/examples/networking-py/Justfile b/examples/networking-py/Justfile index eb90931..7232b12 100644 --- a/examples/networking-py/Justfile +++ b/examples/networking-py/Justfile @@ -11,7 +11,7 @@ export DOCKER_BUILDKIT := "0" kernel := ".unikraft/build/networking-py-hyperlight_hyperlight-x86_64" initrd := "initrd.cpio" -memory := "512Mi" +memory := "32Mi" image := "networking-py-hyperlight" # Run HTTP GET test (raw sockets) diff --git a/examples/python-tools/Justfile b/examples/python-tools/Justfile index a6acd27..a3ad472 100644 --- a/examples/python-tools/Justfile +++ b/examples/python-tools/Justfile @@ -11,7 +11,7 @@ export DOCKER_BUILDKIT := "0" kernel := ".unikraft/build/python-tools-hyperlight_hyperlight-x86_64" initrd := "initrd.cpio" -memory := "96Mi" +memory := "512Mi" image := "python-tools-hyperlight" ghcr_kernel := "ghcr.io/hyperlight-dev/hyperlight-unikraft/python-tools-kernel:latest" diff --git a/host/src/main.rs b/host/src/main.rs index 88bf73d..98f2c4e 100644 --- a/host/src/main.rs +++ b/host/src/main.rs @@ -27,8 +27,8 @@ struct Args { #[arg(long)] initrd: Option, - /// Memory allocation (e.g., 64Mi, 256Mi, 1Gi) - #[arg(long, short = 'm', default_value = "64Mi")] + /// Memory allocation (e.g., 32Mi, 256Mi, 1Gi) + #[arg(long, short = 'm', default_value = "32Mi")] memory: String, /// Stack size (e.g., 8Mi)