Files
go-jdenticon/scripts/benchmark-hotspots.sh
Kevin McIntyre d9e84812ff Initial release: Go Jdenticon library v0.1.0
- Core library with SVG and PNG generation
- CLI tool with generate and batch commands
- Cross-platform path handling for Windows compatibility
- Comprehensive test suite with integration tests
2026-01-03 23:41:48 -05:00

156 lines
5.8 KiB
Bash
Executable File

#!/bin/bash
# Quick Memory Hotspot Validation Script
# Usage: ./scripts/benchmark-hotspots.sh [baseline_dir]
set -e
# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
echo -e "${BLUE}🎯 Go Jdenticon Hotspot Validation${NC}"
echo -e "${BLUE}=================================${NC}"
BASELINE_DIR="${1:-./profiles/baseline}"
TEMP_DIR="./profiles/temp_$(date +%s)"
mkdir -p "$TEMP_DIR"
# Function to run quick benchmark
quick_benchmark() {
local package=$1
local name=$2
echo -e "${BLUE}⚡ Quick benchmark: ${package}${NC}"
go test -bench=BenchmarkGenerate -benchmem -count=3 "./${package}" > "${TEMP_DIR}/${name}_current.txt" 2>&1
}
# Function to extract key metrics
extract_metrics() {
local file=$1
# Extract allocation metrics from benchmark output
grep "BenchmarkGenerate" "$file" | \
awk '{
if (NF >= 5) {
ns_per_op = $3
bytes_per_op = $4
allocs_per_op = $5
gsub(/ns\/op/, "", ns_per_op)
gsub(/B\/op/, "", bytes_per_op)
gsub(/allocs\/op/, "", allocs_per_op)
print bytes_per_op "," allocs_per_op "," ns_per_op
}
}' | tail -1
}
# Function to compare metrics
compare_metrics() {
local baseline_file=$1
local current_file=$2
local component=$3
if [ ! -f "$baseline_file" ]; then
echo -e "${YELLOW}⚠️ No baseline found for ${component}${NC}"
return
fi
baseline_metrics=$(extract_metrics "$baseline_file")
current_metrics=$(extract_metrics "$current_file")
if [ -z "$baseline_metrics" ] || [ -z "$current_metrics" ]; then
echo -e "${RED}❌ Could not extract metrics for ${component}${NC}"
return
fi
IFS=',' read -r baseline_bytes baseline_allocs baseline_ns <<< "$baseline_metrics"
IFS=',' read -r current_bytes current_allocs current_ns <<< "$current_metrics"
# Calculate percentage changes
bytes_change=$(echo "scale=1; ($current_bytes - $baseline_bytes) * 100 / $baseline_bytes" | bc 2>/dev/null || echo "0")
allocs_change=$(echo "scale=1; ($current_allocs - $baseline_allocs) * 100 / $baseline_allocs" | bc 2>/dev/null || echo "0")
time_change=$(echo "scale=1; ($current_ns - $baseline_ns) * 100 / $baseline_ns" | bc 2>/dev/null || echo "0")
echo -e "\n${BLUE}📊 ${component} Comparison:${NC}"
echo -e " Memory: ${baseline_bytes}${current_bytes} B/op (${bytes_change}%)"
echo -e " Allocations: ${baseline_allocs}${current_allocs} allocs/op (${allocs_change}%)"
echo -e " Time: ${baseline_ns}${current_ns} ns/op (${time_change}%)"
# Color code the results
if (( $(echo "$bytes_change < -5" | bc -l 2>/dev/null || echo 0) )); then
echo -e " Status: ${GREEN}🚀 Memory improvement!${NC}"
elif (( $(echo "$bytes_change > 10" | bc -l 2>/dev/null || echo 0) )); then
echo -e " Status: ${RED}⚠️ Memory regression${NC}"
else
echo -e " Status: ${YELLOW}📈 Within normal range${NC}"
fi
}
# Main execution
echo -e "${YELLOW}🔥 Running hotspot validation benchmarks...${NC}\n"
# Run benchmarks for key components
quick_benchmark "internal/engine" "engine"
quick_benchmark "jdenticon" "full"
echo -e "\n${BLUE}📈 Comparing with baseline...${NC}"
# Compare with baseline if available
if [ -d "$BASELINE_DIR" ]; then
compare_metrics "${BASELINE_DIR}/engine_memory_results.txt" "${TEMP_DIR}/engine_current.txt" "Engine"
compare_metrics "${BASELINE_DIR}/full_memory_results.txt" "${TEMP_DIR}/full_current.txt" "Full Library"
else
echo -e "${YELLOW}⚠️ No baseline directory found at: ${BASELINE_DIR}${NC}"
echo -e "${BLUE}💡 Run memory-analysis.sh first to establish baseline${NC}"
fi
# Show current raw results
echo -e "\n${BLUE}📋 Current Raw Results:${NC}"
echo -e "${YELLOW}Engine Package:${NC}"
grep "BenchmarkGenerate" "${TEMP_DIR}/engine_current.txt" | head -5 || echo "No results"
echo -e "\n${YELLOW}Full Library:${NC}"
grep "BenchmarkGenerate" "${TEMP_DIR}/full_current.txt" | head -5 || echo "No results"
# Quick hotspot check
echo -e "\n${BLUE}🔍 Quick Hotspot Status Check:${NC}"
# Check if we're within expected performance bounds
engine_metrics=$(extract_metrics "${TEMP_DIR}/engine_current.txt")
if [ -n "$engine_metrics" ]; then
IFS=',' read -r bytes allocs ns <<< "$engine_metrics"
echo -e "Current Performance:"
echo -e " Memory: ${bytes} B/op"
echo -e " Allocations: ${allocs} allocs/op"
echo -e " Time: ${ns} ns/op"
# Check against known hotspot targets
if (( $(echo "$bytes > 6000" | bc -l 2>/dev/null || echo 0) )); then
echo -e " ${RED}🔥 High memory usage - optimization needed${NC}"
elif (( $(echo "$bytes < 3000" | bc -l 2>/dev/null || echo 0) )); then
echo -e " ${GREEN}✅ Excellent memory efficiency${NC}"
else
echo -e " ${YELLOW}📊 Moderate memory usage${NC}"
fi
if (( $(echo "$allocs > 60" | bc -l 2>/dev/null || echo 0) )); then
echo -e " ${RED}🔥 High allocation count - pooling opportunities${NC}"
elif (( $(echo "$allocs < 30" | bc -l 2>/dev/null || echo 0) )); then
echo -e " ${GREEN}✅ Efficient allocation pattern${NC}"
else
echo -e " ${YELLOW}📊 Moderate allocation count${NC}"
fi
fi
echo -e "\n${BLUE}💡 Quick Commands:${NC}"
echo -e " Set as new baseline: ${YELLOW}cp ${TEMP_DIR}/*_current.txt ${BASELINE_DIR}/${NC}"
echo -e " Full analysis: ${YELLOW}./scripts/memory-analysis.sh${NC}"
echo -e " Profile specific hotspot: ${YELLOW}go test -bench=BenchmarkGenerate -memprofile=temp.prof ./internal/engine && go tool pprof temp.prof${NC}"
# Cleanup
echo -e "\n${GREEN}✅ Hotspot validation completed${NC}"
echo -e "${BLUE}📁 Temp results in: ${TEMP_DIR}${NC}"