From 58133ca4bb3b5c5052b71696b4b06d1d4a26c12a Mon Sep 17 00:00:00 2001 From: Luna Reed Date: Wed, 18 Feb 2026 02:05:27 +0800 Subject: [PATCH] ci: add startup memory budget check --- .github/workflows/pr.yml | 15 ++++++++++++++ Makefile | 8 +++++-- scripts/memory_budget_check.sh | 38 ++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100755 scripts/memory_budget_check.sh diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index fac7597ea..9063ededa 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -56,3 +56,18 @@ jobs: - name: Run go test run: go test ./... + memory-budget: + runs-on: ubuntu-latest + needs: fmt-check + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + + - name: Check startup memory budget + run: make memory-check + diff --git a/Makefile b/Makefile index bb31243dd..bb24918f3 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: all build install uninstall clean help test +.PHONY: all build install uninstall clean help test memory-check # Build variables BINARY_NAME=picoclaw @@ -126,10 +126,14 @@ clean: vet: @$(GO) vet ./... -## fmt: Format Go code +## test: Run unit tests test: @$(GO) test ./... +## memory-check: Validate startup memory stays under budget (default 20MB RSS) +memory-check: + @bash ./scripts/memory_budget_check.sh + ## fmt: Format Go code fmt: @$(GO) fmt ./... diff --git a/scripts/memory_budget_check.sh b/scripts/memory_budget_check.sh new file mode 100755 index 000000000..33f8edaf2 --- /dev/null +++ b/scripts/memory_budget_check.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +BINARY_PATH="${PICOCLAW_BINARY_PATH:-${ROOT_DIR}/build/picoclaw}" +BUDGET_KB="${PICOCLAW_MEMORY_BUDGET_KB:-20480}" + +if [[ ! -x "${BINARY_PATH}" ]]; then + echo "[memory-check] binary not found at ${BINARY_PATH}; building..." + make -C "${ROOT_DIR}" build >/dev/null +fi + +tmp_time_out="$(mktemp)" +trap 'rm -f "${tmp_time_out}"' EXIT + +if [[ "$(uname -s)" == "Darwin" ]]; then + /usr/bin/time -l "${BINARY_PATH}" version >/dev/null 2>"${tmp_time_out}" + rss_bytes="$(awk '/maximum resident set size/{print $1}' "${tmp_time_out}" | tail -n1)" + rss_kb="$((rss_bytes / 1024))" +else + /usr/bin/time -v "${BINARY_PATH}" version >/dev/null 2>"${tmp_time_out}" + rss_kb="$(awk -F: '/Maximum resident set size/{gsub(/^[ \t]+/, "", $2); print $2}' "${tmp_time_out}" | tail -n1)" +fi + +if [[ -z "${rss_kb}" ]]; then + echo "[memory-check] failed to parse peak RSS from /usr/bin/time output" + cat "${tmp_time_out}" + exit 1 +fi + +echo "[memory-check] peak RSS: ${rss_kb} KiB (budget: ${BUDGET_KB} KiB)" + +if (( rss_kb > BUDGET_KB )); then + echo "[memory-check] FAILED: peak RSS exceeds budget" + exit 1 +fi + +echo "[memory-check] PASS"