name: Comprehensive Profiling Benchmarks
on:
workflow_dispatch:
inputs:
mode:
description: "Profiling mode"
required: false
default: "development"
type: choice
options:
- "development"
- "production"
benchmark_filter:
description: 'Benchmark filter (optional - e.g., "triangulation_scaling" or "memory_profiling")'
required: false
default: ""
type: string
schedule:
- cron: "0 2 1-7 * 0"
push:
tags:
- "v*.*.*"
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
RUST_TOOLCHAIN: 1.92.0
jobs:
comprehensive-profiling:
name: Comprehensive Performance Profiling
runs-on: ubuntu-latest
timeout-minutes: 360
steps:
- name: Checkout code
uses: actions/checkout@v6.0.2
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.RUST_TOOLCHAIN }}
- name: Cache Cargo dependencies
uses: actions/cache@v5
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-profiling-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-profiling-
${{ runner.os }}-cargo-
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential
- name: Set profiling mode
run: |
INPUT_MODE="${{ github.event.inputs.mode || 'development' }}"
# Profiling mode determination:
# 1. Tag pushes (github.event_name == "push"): Always use development mode
# - Avoids CI timeout issues on release tag creation
# - Provides quick performance snapshot (~1-2 hours runtime)
# - Full profiling can be triggered manually if needed
# 2. Manual dispatch with mode="development": Use development mode
# 3. Scheduled runs and manual dispatch with mode="production": Use production mode
# - Full scale testing (10³-10⁶ points)
# - May take 4-6 hours
if [[ "$INPUT_MODE" == "development" ]] || [[ "${{ github.event_name }}" == "push" ]]; then
echo "PROFILING_DEV_MODE=1" >> "$GITHUB_ENV"
echo "Running in development mode (reduced scale)"
# Smaller, faster dev runs
{
echo "BENCH_SAMPLE_SIZE=30"
echo "BENCH_WARMUP_SECS=2"
echo "BENCH_MEASUREMENT_TIME=3"
# Keep 4D reduced set (no BENCH_LARGE_SCALE)
} >> "$GITHUB_ENV"
else
echo "Running in production mode (full scale)"
# Heavier production runs
{
echo "BENCH_SAMPLE_SIZE=100"
echo "BENCH_WARMUP_SECS=5"
echo "BENCH_MEASUREMENT_TIME=10"
echo "BENCH_LARGE_SCALE=1" # enable 4D @ 10K
} >> "$GITHUB_ENV"
fi
- name: Build profiling suite
run: |
cargo build --release --bench profiling_suite
- name: Run comprehensive profiling benchmarks
run: |
# Create results directory
mkdir -p profiling-results
# Set benchmark filter if provided
BENCH_FILTER=""
if [[ -n "${{ github.event.inputs.benchmark_filter || '' }}" ]]; then
BENCH_FILTER="-- ${{ github.event.inputs.benchmark_filter }}"
fi
# Run profiling (timing-focused)
echo "Starting comprehensive profiling benchmarks..."
# Determine if memory profiling is requested via filter
# Match memory_profiling group specifically (not just any "memory" substring)
MEMORY_FEATURES=""
if [[ "$BENCH_FILTER" =~ (^|[[:space:]])memory_profiling($|[[:space:]]) ]]; then
MEMORY_FEATURES="--features count-allocations"
echo "MEMORY_BENCHMARKS_RUN=true" >> "$GITHUB_ENV"
fi
# shellcheck disable=SC2086
cargo bench --bench profiling_suite $MEMORY_FEATURES "${BENCH_FILTER:-}" \
2>&1 | tee profiling-results/profiling_output.log
- name: Run profiling with memory allocation tracking (if not already done)
if: env.MEMORY_BENCHMARKS_RUN != 'true'
run: |
echo "Running memory-specific profiling with allocation tracking..."
cargo bench --bench profiling_suite --features count-allocations -- memory_profiling \
2>&1 | tee profiling-results/memory_profiling_detailed.log
- name: Generate profiling summary
run: |
# Create a summary of the profiling run
cat > profiling-results/profiling_summary.md << EOF
# Comprehensive Profiling Results
**Date**: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
**Commit**: ${{ github.sha }}
**Branch**: ${{ github.ref_name }}
**Trigger**: ${{ github.event_name }}
**Mode**: ${{ env.PROFILING_DEV_MODE == '1' && 'Development' || 'Production' }}
**Runner**: ${{ runner.os }}
## Configuration
- **Profiling Mode**: ${{ env.PROFILING_DEV_MODE == '1' &&
'Development (reduced scale for faster iteration)' ||
'Production (full 10³-10⁶ point scale)' }}
- **Memory Tracking**: ${{ contains(github.event.inputs.benchmark_filter || '', 'memory') &&
'Enabled for memory benchmarks (count-allocations feature)' ||
'Enabled only for memory-specific runs' }}
- **Benchmark Filter**: ${{ (github.event.inputs.benchmark_filter || '') != '' &&
github.event.inputs.benchmark_filter || 'All benchmarks' }}
## Benchmark Categories Run
- **Triangulation Scaling**: Large-scale triangulation performance (2D-5D)
- **Memory Profiling**: Memory allocation tracking and analysis
- **Query Latency**: Circumsphere containment query performance
- **Algorithmic Bottlenecks**: Boundary facets and convex hull operations
## Point Distributions Tested
- **Random**: Uniform random distribution
- **Grid**: Regular grid pattern (best-case scenario)
- **Poisson Disk**: Spatially uniform distribution (realistic scenario)
## Files Generated
- \`profiling_output.log\`: Complete benchmark output
- \`memory_profiling_detailed.log\`: Detailed memory allocation analysis
- \`criterion/\`: HTML reports and detailed timing data
EOF
# Publish summary to job summary UI for quick visibility
cat profiling-results/profiling_summary.md >> "$GITHUB_STEP_SUMMARY"
- name: Save profiling baseline for tagged release
if: startsWith(github.ref, 'refs/tags/')
run: |
# For tagged releases, save as new baseline
echo "Tagged release detected - this will serve as new profiling baseline"
cp -r target/criterion profiling-results/criterion-baseline-${{ github.ref_name }}
- name: Upload profiling results
uses: actions/upload-artifact@v7
with:
name: profiling-results-${{ github.run_number }}
path: profiling-results/
retention-days: 30
- name: Upload profiling baseline (for tagged releases)
if: startsWith(github.ref, 'refs/tags/')
uses: actions/upload-artifact@v7
with:
name: profiling-baseline-${{ github.ref_name }}
path: |
profiling-results/
target/criterion/
retention-days: 90
- name: Log completion (if triggered manually)
if: github.event_name == 'workflow_dispatch'
run: |
echo "Manual profiling run completed for commit ${{ github.sha }}"
echo "Check the Actions tab for detailed results and artifacts"
memory-stress-test:
name: Memory Stress Testing
runs-on: ubuntu-latest
timeout-minutes: 90
env:
PROFILING_DEV_MODE: "1"
BENCH_SAMPLE_SIZE: "10"
BENCH_WARMUP_SECS: "1"
BENCH_MEASUREMENT_TIME: "5"
BENCH_PERCENTILE: "95"
steps:
- name: Checkout code
uses: actions/checkout@v6.0.2
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.RUST_TOOLCHAIN }}
- name: Cache Cargo dependencies
uses: actions/cache@v5
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-memory-${{ hashFiles('**/Cargo.lock') }}
- name: Run allocation API tests
run: |
echo "Running allocation API tests..."
cargo test --test allocation_api --features count-allocations --verbose
- name: Run memory scaling benchmarks
env:
PROFILING_DEV_MODE: "1"
BENCH_SAMPLE_SIZE: "10"
BENCH_WARMUP_SECS: "1"
BENCH_MEASUREMENT_TIME: "5"
BENCH_PERCENTILE: "95"
run: |
echo "Running memory profiling analysis with CI-friendly configuration..."
echo "PROFILING_DEV_MODE=$PROFILING_DEV_MODE"
echo "BENCH_SAMPLE_SIZE=$BENCH_SAMPLE_SIZE"
echo "BENCH_WARMUP_SECS=$BENCH_WARMUP_SECS"
echo "BENCH_MEASUREMENT_TIME=$BENCH_MEASUREMENT_TIME"
cargo bench --bench profiling_suite --features count-allocations -- memory_profiling
- name: Upload memory test results
uses: actions/upload-artifact@v7
with:
name: memory-stress-results-${{ github.run_number }}
path: |
target/criterion/
retention-days: 14