From eb72b987ecd20480804a73cc32d16c023f948913 Mon Sep 17 00:00:00 2001 From: vprashar2929 Date: Mon, 11 Aug 2025 16:33:08 +0530 Subject: [PATCH] chore: add script for profiling Signed-off-by: vprashar2929 --- .github/workflows/profiling.yaml | 111 +++++++++++++++++++++++++++++++ hack/reports/profiling.sh | 91 +++++++++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 .github/workflows/profiling.yaml create mode 100755 hack/reports/profiling.sh diff --git a/.github/workflows/profiling.yaml b/.github/workflows/profiling.yaml new file mode 100644 index 0000000000..3f16a3f472 --- /dev/null +++ b/.github/workflows/profiling.yaml @@ -0,0 +1,111 @@ +name: Profiling Report +# This configuration runs two separate workflows for PRs +# 1. On 'pull_request': Builds and run pprof profiling scripts +# 2. On 'pull_request_target': Deploys the artifacts from (1) with write permissions +on: + pull_request: + pull_request_target: + +permissions: + contents: write # Needed for gh-pages push + pull-requests: write # Needed for PR comment + +jobs: + # Job 1: Run on the PR from the fork with a read-only token + build_and_profile: + # This job only runs for the 'pull_request' event, not 'pull_request_target' + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - name: Checkout source + uses: actions/checkout@v4 + # This explicitly checks out the head of the pull request + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Build Kepler + run: | + make build + + - name: Enable fake cpu meter + shell: bash + run: | + sed -i '/fake-cpu-meter:/{n;s/enabled: false/enabled: true/}' hack/config.yaml + + - name: Run Kepler in the background + run: | + nohup ./bin/kepler --config.file=hack/config.yaml > kepler.log 2>&1 & + + - name: Run profiling script + run: | + ./hack/reports/profiling.sh + + - name: Upload profiling artifacts + uses: actions/upload-artifact@v4 + with: + name: profiling-results-${{ github.event.pull_request.number }} + path: ./tmp + retention-days: 1 # Keep artifact for 1 day + + - name: Run must gather + shell: bash + run: | + echo "::group::Get logs for kepler" + cat kepler.log || true + echo "::endgroup::" + + echo "::group::Fetch metrics from localhost:28282" + curl -s http://localhost:28282/metrics || true + echo "::endgroup::" + + # Job 2: Run in the context of the base repo with a write token + deploy_and_comment: + # This job only runs for the 'pull_request_target' event + if: github.event_name == 'pull_request_target' + runs-on: ubuntu-latest + # It requires the build_and_profile job from the corresponding 'pull_request' workflow to succeed + needs: build_and_profile + steps: + - name: Checkout source + uses: actions/checkout@v4 + # Checks out the base branch of the PR, NOT the fork's code + + - name: Download rofiling artifacts + uses: actions/download-artifact@v4 + with: + name: profiling-results-${{ github.event.pull_request.number }} + path: ./tmp + + - name: Deploy to GitHub Pages + id: deployment + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./tmp + destination_dir: pr-${{ github.event.pull_request.number }} + keep_files: false + user_name: github-actions[bot] + user_email: github-actions[bot]@users.noreply.github.com + + - name: Generate comment message + id: generate_message + run: | + { + echo "message<> $GITHUB_OUTPUT + + - name: Create PR Comment with report links + uses: thollander/actions-comment-pull-request@v3 + with: + message: ${{ steps.generate_message.outputs.message }} diff --git a/hack/reports/profiling.sh b/hack/reports/profiling.sh new file mode 100755 index 0000000000..58ac9146e3 --- /dev/null +++ b/hack/reports/profiling.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash + +set -eu -o pipefail +trap cleanup INT EXIT + +# config +declare DURATION=${DURATION:-30} +declare KEPLER_PORT=${KEPLER_PORT:-28282} + +# constants +PROJECT_ROOT="$(git rev-parse --show-toplevel)" +declare -r PROJECT_ROOT +declare -r TMP_DIR="$PROJECT_ROOT/tmp" +declare -r CPU_PROFILE_DIR="$TMP_DIR/cpu-profile" +declare -r MEM_PROFILE_DIR="$TMP_DIR/mem-profile" +declare -r KEPLER_BIN_DIR="$PROJECT_ROOT/bin" +declare -r CPU_HTTP_PORT=29000 +declare -r MEM_HTTP_PORT=29001 + +source "$PROJECT_ROOT/hack/utils.bash" + +cleanup() { + info "Cleaning up ..." + # Terminate all background jobs (e.g. pprof servers) + { jobs -p | xargs -I {} -- pkill -TERM -P {}; } || true + wait + sleep 1 + + return 0 +} + +capture_cpu_profile() { + run go tool pprof -proto -seconds "$DURATION" \ + -output "$CPU_PROFILE_DIR"/profile.pb.gz "$KEPLER_BIN_DIR/kepler" \ + "http://localhost:$KEPLER_PORT/debug/pprof/profile" || return 1 + + # Start pprof web server in background + run go tool pprof --http "localhost:$CPU_HTTP_PORT" --no_browser \ + "$KEPLER_BIN_DIR/kepler" "$CPU_PROFILE_DIR/profile.pb.gz"