161 lines
4.4 KiB
Bash
161 lines
4.4 KiB
Bash
|
|
#!/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 "$@"
|