#!/bin/bash # build_pgo.sh - HAKMEM PGO (Profile-Guided Optimization) Build Script # Usage: ./build_pgo.sh [clean|profile|build|all] # # Phase 8.4: Automated PGO build for maximum performance # Expected: 300-350M ops/sec (vs 200-220M normal build) set -e # Exit on error BENCHMARK="bench_comprehensive_hakmem" PROFILE_RUN="HAKMEM_WRAP_TINY=1" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color log() { echo -e "${BLUE}[PGO]${NC} $1" } success() { echo -e "${GREEN}✓${NC} $1" } warn() { echo -e "${YELLOW}⚠${NC} $1" } error() { echo -e "${RED}✗${NC} $1" exit 1 } # Step 0: Clean previous builds clean() { log "Cleaning previous builds..." make clean > /dev/null 2>&1 || true rm -f *.gcda *.o ${BENCHMARK} 2>/dev/null || true success "Clean complete" } # Step 1: Build with profiling instrumentation build_instrumented() { log "Step 1/3: Building instrumented binary..." # Get base flags from Makefile and add PGO instrumentation BASE_CFLAGS="-O3 -march=native -mtune=native -Wall -Wextra -std=c11 -D_GNU_SOURCE -D_POSIX_C_SOURCE=199309L -DHAKMEM_DEBUG_TIMING=0 -ffast-math -funroll-loops" BASE_LDFLAGS="-lm -lpthread" make CFLAGS="$BASE_CFLAGS -fprofile-generate -flto" \ LDFLAGS="$BASE_LDFLAGS -fprofile-generate -flto" \ ${BENCHMARK} 2>&1 | tail -5 if [ ! -f "${BENCHMARK}" ]; then error "Instrumented build failed!" fi success "Instrumented build complete" } # Step 2: Collect profile data collect_profile() { log "Step 2/3: Running profile workload..." echo -e "${YELLOW}Running benchmark to collect profile data...${NC}" # Run with a time budget to ensure exit and profile write-out timeout -s INT 20 ${PROFILE_RUN} ./${BENCHMARK} 2>&1 | grep -E "(Test 1:|Throughput:)" | head -6 || true # Check if profile data was generated (any .gcda) GCDA_COUNT=$(ls -1 *.gcda 2>/dev/null | wc -l || echo 0) if [ "${GCDA_COUNT}" -eq 0 ]; then error "Profile data not generated!" fi success "Profile data collected (${GCDA_COUNT} *.gcda files)" } # Step 3: Build optimized binary using profile build_optimized() { log "Step 3/3: Building PGO-optimized binary..." # Remove old .o files but keep .gcda rm -f *.o ${BENCHMARK} # Add -Wno-error=coverage-mismatch to avoid PGO warnings BASE_CFLAGS="-O3 -march=native -mtune=native -Wall -Wextra -std=c11 -D_GNU_SOURCE -D_POSIX_C_SOURCE=199309L -DHAKMEM_DEBUG_TIMING=0 -ffast-math -funroll-loops" BASE_LDFLAGS="-lm -lpthread" make CFLAGS="$BASE_CFLAGS -fprofile-use -flto -Wno-error=coverage-mismatch" \ LDFLAGS="$BASE_LDFLAGS -fprofile-use -flto" \ ${BENCHMARK} 2>&1 | grep -v "coverage mismatch" | tail -5 if [ ! -f "${BENCHMARK}" ]; then error "PGO-optimized build failed!" fi success "PGO-optimized build complete" } # Quick benchmark to verify performance quick_bench() { log "Running quick performance check..." echo "" ./${BENCHMARK} 2>&1 | grep -E "(128 B|Throughput:|Long-lived)" | head -10 echo "" } # Main workflow main() { local mode="${1:-all}" echo "" echo "=========================================" echo " HAKMEM PGO Build Script (Phase 8.4)" echo "=========================================" echo "" case "$mode" in clean) clean ;; profile) clean build_instrumented collect_profile ;; build) if [ ! -f "hakmem_tiny.gcda" ]; then error "No profile data found! Run './build_pgo.sh profile' first" fi build_optimized quick_bench ;; all) clean build_instrumented collect_profile build_optimized echo "" success "PGO build complete! Expected: 300-350M ops/sec" warn "Run './bench_comprehensive_hakmem' for full benchmark" echo "" ;; *) echo "Usage: $0 [clean|profile|build|all]" echo "" echo " clean - Clean previous builds" echo " profile - Build instrumented + collect profile" echo " build - Build optimized using existing profile" echo " all - Full PGO build (default)" echo "" exit 1 ;; esac } main "$@"