#!/bin/bash # Comprehensive Memory Profiling Script for go-jdenticon # Usage: ./scripts/memory-analysis.sh [output_dir] set -e # Configuration OUTPUT_DIR="${1:-./profiles}" TIMESTAMP=$(date +"%Y%m%d_%H%M%S") REPORT_DIR="${OUTPUT_DIR}/report_${TIMESTAMP}" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color echo -e "${BLUE}๐Ÿ” Go Jdenticon Memory Analysis${NC}" echo -e "${BLUE}================================${NC}" # Create output directories mkdir -p "${REPORT_DIR}" echo -e "${YELLOW}๐Ÿ“ Output directory: ${REPORT_DIR}${NC}" # Function to run memory profiling benchmark run_memory_benchmark() { local package=$1 local profile_name=$2 local benchmark_pattern=${3:-"."} echo -e "${BLUE}๐Ÿงช Running memory benchmark: ${package}${NC}" go test -bench="${benchmark_pattern}" \ -memprofile="${REPORT_DIR}/${profile_name}.prof" \ -benchmem \ -benchtime=3s \ "./${package}" > "${REPORT_DIR}/${profile_name}_results.txt" 2>&1 if [ $? -eq 0 ]; then echo -e "${GREEN}โœ… ${package} profiling completed${NC}" else echo -e "${RED}โŒ ${package} profiling failed${NC}" return 1 fi } # Function to analyze memory profile analyze_profile() { local profile_path=$1 local analysis_name=$2 echo -e "${BLUE}๐Ÿ“Š Analyzing ${analysis_name}${NC}" # Generate top allocations go tool pprof -top "${profile_path}" > "${REPORT_DIR}/${analysis_name}_top.txt" 2>/dev/null # Generate allocation list for hotspot functions go tool pprof -list="renderShape|AddPolygon|GenerateColorTheme|svgValue" "${profile_path}" > "${REPORT_DIR}/${analysis_name}_hotspots.txt" 2>/dev/null # Generate memory usage by package go tool pprof -top -cum "${profile_path}" > "${REPORT_DIR}/${analysis_name}_cumulative.txt" 2>/dev/null echo -e "${GREEN}โœ… ${analysis_name} analysis completed${NC}" } # Function to generate comparison report generate_comparison() { local baseline_prof=$1 local current_prof=$2 local comparison_name=$3 if [ -f "${baseline_prof}" ] && [ -f "${current_prof}" ]; then echo -e "${BLUE}๐Ÿ”„ Generating comparison: ${comparison_name}${NC}" go tool pprof -base="${baseline_prof}" -top "${current_prof}" > "${REPORT_DIR}/${comparison_name}_diff.txt" 2>/dev/null echo -e "${GREEN}โœ… Comparison ${comparison_name} completed${NC}" fi } # Main execution echo -e "${YELLOW}๐Ÿš€ Starting memory profiling...${NC}" # 1. Profile engine package echo -e "\n${BLUE}1. Engine Package Profiling${NC}" run_memory_benchmark "internal/engine" "engine_memory" # 2. Profile renderer package echo -e "\n${BLUE}2. Renderer Package Profiling${NC}" run_memory_benchmark "internal/renderer" "renderer_memory" # 3. Profile full library echo -e "\n${BLUE}3. Full Library Profiling${NC}" run_memory_benchmark "jdenticon" "full_memory" # 4. Analyze profiles echo -e "\n${BLUE}4. Analyzing Memory Profiles${NC}" for profile in "${REPORT_DIR}"/*.prof; do if [ -f "$profile" ]; then basename=$(basename "$profile" .prof) analyze_profile "$profile" "$basename" fi done # 5. Generate comparison with baseline if available BASELINE_DIR="./profiles/baseline" if [ -d "$BASELINE_DIR" ]; then echo -e "\n${BLUE}5. Comparing with Baseline${NC}" for profile in "${REPORT_DIR}"/*.prof; do basename=$(basename "$profile") if [ -f "${BASELINE_DIR}/${basename}" ]; then comparison_name=$(basename "$basename" .prof) generate_comparison "${BASELINE_DIR}/${basename}" "$profile" "$comparison_name" fi done fi # 6. Generate summary report echo -e "\n${BLUE}6. Generating Summary Report${NC}" cat > "${REPORT_DIR}/ANALYSIS_SUMMARY.md" << EOF # Memory Analysis Report - ${TIMESTAMP} ## Benchmark Results ### Engine Package \`\`\` $(cat "${REPORT_DIR}/engine_memory_results.txt" | grep "Benchmark" | head -10) \`\`\` ### Renderer Package \`\`\` $(cat "${REPORT_DIR}/renderer_memory_results.txt" | grep "Benchmark" | head -10) \`\`\` ### Full Library \`\`\` $(cat "${REPORT_DIR}/full_memory_results.txt" | grep "Benchmark" | head -10) \`\`\` ## Top Memory Allocations ### Engine Hotspots \`\`\` $(head -20 "${REPORT_DIR}/engine_memory_top.txt") \`\`\` ### Renderer Hotspots \`\`\` $(head -20 "${REPORT_DIR}/renderer_memory_top.txt") \`\`\` ## Analysis Files Generated - \`*_top.txt\`: Top allocation sources - \`*_hotspots.txt\`: Known hotspot function analysis - \`*_cumulative.txt\`: Cumulative allocation by package - \`*_diff.txt\`: Comparison with baseline (if available) ## Next Steps 1. Review top allocation sources in \`*_top.txt\` files 2. Focus optimization on functions listed in hotspot analysis 3. Use \`go tool pprof\` for interactive analysis: \`\`\`bash go tool pprof ${REPORT_DIR}/engine_memory.prof \`\`\` EOF echo -e "${GREEN}โœ… Summary report generated${NC}" # 7. Interactive analysis option echo -e "\n${YELLOW}๐ŸŽฏ Analysis complete!${NC}" echo -e "${BLUE}๐Ÿ“ Results saved to: ${REPORT_DIR}${NC}" echo -e "\n${YELLOW}Quick commands for manual analysis:${NC}" echo -e " ${BLUE}Interactive engine analysis:${NC} go tool pprof ${REPORT_DIR}/engine_memory.prof" echo -e " ${BLUE}Interactive renderer analysis:${NC} go tool pprof ${REPORT_DIR}/renderer_memory.prof" echo -e " ${BLUE}Web interface:${NC} go tool pprof -http=:8080 ${REPORT_DIR}/engine_memory.prof" # 8. Set baseline option if [ ! -d "./profiles/baseline" ]; then echo -e "\n${YELLOW}๐Ÿ’ก Tip: Set this as baseline for future comparisons?${NC}" echo -e " ${BLUE}mkdir -p ./profiles/baseline && cp ${REPORT_DIR}/*.prof ./profiles/baseline/${NC}" fi echo -e "\n${GREEN}๐ŸŽ‰ Memory analysis completed successfully!${NC}"