lolly/Makefile
xfy 766e9255fa feat(config,server,makefile): 新增 pprof 性能分析端点支持
- 新增 PprofConfig 配置结构,支持路径和 IP 访问控制
- 实现 PprofHandler 处理器,提供 CPU/heap/goroutine/block/mutex profile
- Makefile 新增 build-perf、build-pgo、pgo-collect 目标
- 支持 PGO (Profile-Guided Optimization) 构建

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-07 18:21:03 +08:00

318 lines
10 KiB
Makefile
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Makefile - Lolly Build Commands
# 版本信息
APP_NAME := lolly
VERSION := 0.1.0
GIT_COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown")
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
BUILD_TIME := $(shell date -u '+%Y-%m-%d %H:%M:%S UTC')
GO_VERSION := $(shell go version | awk '{print $$3}')
BUILD_PLATFORM := $(shell go env GOOS)/$(shell go env GOARCH)
BUILD_DIR := bin
# 生产构建标志(体积优化)
LDFLAGS := -ldflags "-s -w \
-X 'rua.plus/lolly/internal/app.Version=$(VERSION)' \
-X 'rua.plus/lolly/internal/app.GitCommit=$(GIT_COMMIT)' \
-X 'rua.plus/lolly/internal/app.GitBranch=$(GIT_BRANCH)' \
-X 'rua.plus/lolly/internal/app.BuildTime=$(BUILD_TIME)' \
-X 'rua.plus/lolly/internal/app.GoVersion=$(GO_VERSION)' \
-X 'rua.plus/lolly/internal/app.BuildPlatform=$(BUILD_PLATFORM)'"
# 运行时性能优化标志
PERF_GCFLAGS := -gcflags="-l=4"
PERF_ASMFLAGS := -asmflags="-l=4"
# Go 文件
MAIN_PATH := main.go
# 默认目标
.DEFAULT_GOAL := build
# ============================================
# 构建命令
# ============================================
# 本地构建
build:
@echo "Building $(APP_NAME)..."
@mkdir -p $(BUILD_DIR)
go build $(LDFLAGS) -o $(BUILD_DIR)/$(APP_NAME) $(MAIN_PATH)
@echo "Built: $(BUILD_DIR)/$(APP_NAME)"
@echo "Version: $(VERSION) | Commit: $(GIT_COMMIT) | Platform: $(BUILD_PLATFORM)"
# 生产构建(体积优化)
build-prod:
@echo "Building $(APP_NAME) for production..."
@mkdir -p $(BUILD_DIR)
go build $(LDFLAGS) -trimpath -o $(BUILD_DIR)/$(APP_NAME) $(MAIN_PATH)
@echo "Production build complete: $(BUILD_DIR)/$(APP_NAME)"
# 生产构建(最大运行时性能)
build-perf:
@echo "Building $(APP_NAME) with max runtime performance..."
@mkdir -p $(BUILD_DIR)
go build $(LDFLAGS) $(PERF_GCFLAGS) $(PERF_ASMFLAGS) -trimpath \
-o $(BUILD_DIR)/$(APP_NAME) $(MAIN_PATH)
@echo "Performance build complete: $(BUILD_DIR)/$(APP_NAME)"
# PGO 构建(需先收集 profile
PGO_PROFILE ?= default.pgo
build-pgo:
@echo "Building $(APP_NAME) with PGO optimization..."
@mkdir -p $(BUILD_DIR)
if [ -f $(PGO_PROFILE) ]; then \
go build $(LDFLAGS) $(PERF_GCFLAGS) $(PERF_ASMFLAGS) -trimpath \
-pgo=$(PGO_PROFILE) -o $(BUILD_DIR)/$(APP_NAME) $(MAIN_PATH); \
echo "PGO build complete using: $(PGO_PROFILE)"; \
else \
echo "PGO profile not found: $(PGO_PROFILE)"; \
echo "Run 'make pgo-collect' first to generate profile"; \
exit 1; \
fi
# 收集 PGO profile运行代表性 workload
pgo-collect:
@echo "=== PGO Profile Collection Guide ==="
@echo ""
@echo "Step 1: Enable pprof in your config file:"
@echo " monitoring:"
@echo " pprof:"
@echo " enabled: true"
@echo " path: /debug/pprof"
@echo " allow: [\"127.0.0.1\"]"
@echo ""
@echo "Step 2: Build and run lolly with representative workload:"
@echo " make build && ./bin/lolly -c configs/lolly.yaml"
@echo ""
@echo "Step 3: Collect CPU profile (run during peak load):"
@echo " curl http://localhost:<port>/debug/pprof/profile?seconds=30 > $(PGO_PROFILE)"
@echo ""
@echo "Step 4: Build with PGO optimization:"
@echo " make build-pgo"
@echo ""
@echo "Available pprof endpoints:"
@echo " /debug/pprof - Index page"
@echo " /debug/pprof/profile - CPU profile (add ?seconds=N)"
@echo " /debug/pprof/heap - Memory profile"
@echo " /debug/pprof/goroutine - Goroutine count"
@echo ""
@echo "Tip: Profile during real workload for best PGO results"
# 跨平台构建
build-linux:
@echo "Building for Linux..."
@mkdir -p $(BUILD_DIR)
GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -trimpath -o $(BUILD_DIR)/$(APP_NAME)-linux-amd64 $(MAIN_PATH)
@echo "Built: $(BUILD_DIR)/$(APP_NAME)-linux-amd64"
build-darwin:
@echo "Building for macOS..."
@mkdir -p $(BUILD_DIR)
GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -trimpath -o $(BUILD_DIR)/$(APP_NAME)-darwin-amd64 $(MAIN_PATH)
GOOS=darwin GOARCH=arm64 go build $(LDFLAGS) -trimpath -o $(BUILD_DIR)/$(APP_NAME)-darwin-arm64 $(MAIN_PATH)
@echo "Built: $(BUILD_DIR)/$(APP_NAME)-darwin-{amd64,arm64}"
build-windows:
@echo "Building for Windows..."
@mkdir -p $(BUILD_DIR)
GOOS=windows GOARCH=amd64 go build $(LDFLAGS) -trimpath -o $(BUILD_DIR)/$(APP_NAME)-windows-amd64.exe $(MAIN_PATH)
@echo "Built: $(BUILD_DIR)/$(APP_NAME)-windows-amd64.exe"
# 构建所有平台
build-all: build-linux build-darwin build-windows
@echo "All platform builds complete."
# ============================================
# 开发命令
# ============================================
# 运行开发服务器
run:
@echo "Running $(APP_NAME) in development mode..."
go run $(MAIN_PATH) -c configs/lolly.yaml
# 测试配置
test-config:
@echo "Testing configuration..."
go run $(MAIN_PATH) -t -c configs/lolly.yaml
# 显示版本
version:
@echo "$(APP_NAME) version $(VERSION)"
@echo "Git: $(GIT_COMMIT) ($(GIT_BRANCH))"
@echo "Built: $(BUILD_TIME)"
@echo "Go: $(GO_VERSION)"
# ============================================
# 测试命令
# ============================================
# 运行所有测试
test:
@echo "Running tests..."
go test -v ./...
# 运行测试(带覆盖率)
test-cover:
@echo "Running tests with coverage..."
go test -v -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
@echo "Coverage report: coverage.html"
# 运行基准测试
bench:
@echo "Running benchmarks..."
go test -bench=. -benchmem ./...
# 运行基准测试统计模式10次采样
bench-stat:
@echo "Running benchmarks with statistical sampling..."
go test -bench=. -benchmem -count=10 ./... | tee benchmark-current.txt
# 对比基准测试结果(需要 benchstat
bench-compare:
@echo "Comparing benchmarks..."
@if command -v benchstat >/dev/null 2>&1; then \
if [ -f benchmark-baseline.txt ]; then \
benchstat benchmark-baseline.txt benchmark-current.txt; \
else \
echo "基准线文件 benchmark-baseline.txt 不存在,运行当前基准测试..."; \
$(MAKE) bench-stat; \
fi \
else \
echo "benchstat 未安装,运行: go install golang.org/x/perf/cmd/benchstat@latest"; \
exit 1; \
fi
# 保存当前基准结果为基准线
bench-save:
@echo "Saving benchmark baseline..."
@if [ -f benchmark-current.txt ]; then \
cp benchmark-current.txt benchmark-baseline.txt; \
echo "基准线已保存到 benchmark-baseline.txt"; \
else \
echo "运行基准测试并保存..."; \
$(MAKE) bench-stat; \
cp benchmark-current.txt benchmark-baseline.txt; \
fi
# 检查性能回归(需要 Python
bench-check:
@echo "Checking for performance regressions..."
@if [ -f benchmark-comparison.txt ]; then \
python scripts/check_regression.py benchmark-comparison.txt; \
elif command -v benchstat >/dev/null 2>&1 && [ -f benchmark-baseline.txt ] && [ -f benchmark-current.txt ]; then \
benchstat benchmark-baseline.txt benchmark-current.txt > benchmark-comparison.txt; \
python scripts/check_regression.py benchmark-comparison.txt; \
else \
echo "需要 benchstat 和基准线/当前结果文件"; \
echo "运行: make bench-save && make bench-stat && make bench-check"; \
exit 1; \
fi
# ============================================
# 代码质量
# ============================================
# 格式化代码
fmt:
@echo "Formatting code..."
go fmt ./...
# 静态检查
lint:
@echo "Running linter..."
@if command -v golangci-lint >/dev/null 2>&1; then \
golangci-lint run ./...; \
else \
echo "golangci-lint not installed. Run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest"; \
go vet ./...; \
fi
# 代码检查
check: fmt lint test
@echo "All checks passed."
# ============================================
# 依赖管理
# ============================================
# 下载依赖
deps:
@echo "Downloading dependencies..."
go mod download
go mod tidy
# 更新依赖
update-deps:
@echo "Updating dependencies..."
go get -u ./...
go mod tidy
# ============================================
# 安装命令
# ============================================
# 安装到系统
install:
@echo "Installing $(APP_NAME)..."
go install $(LDFLAGS) $(MAIN_PATH)
@echo "Installed to: $(shell go env GOPATH)/bin/$(APP_NAME)"
# ============================================
# 清理命令
# ============================================
# 清理构建产物
clean:
@echo "Cleaning build artifacts..."
rm -rf $(BUILD_DIR)
rm -f coverage.out coverage.html
@echo "Clean complete."
# ============================================
# 帮助
# ============================================
help:
@echo "$(APP_NAME) Makefile Commands"
@echo ""
@echo "Build:"
@echo " make build - Build for current platform"
@echo " make build-prod - Production build (size optimized)"
@echo " make build-perf - Production build (max runtime performance)"
@echo " make build-pgo - PGO build (needs profile, use PGO_PROFILE=path)"
@echo " make pgo-collect - Guide for collecting PGO profile"
@echo " make build-all - Build for all platforms"
@echo " make build-linux - Build for Linux amd64"
@echo " make build-darwin - Build for macOS (amd64 + arm64)"
@echo " make build-windows - Build for Windows amd64"
@echo ""
@echo "Development:"
@echo " make run - Run development server"
@echo " make test-config - Test configuration file"
@echo " make version - Show version info"
@echo ""
@echo "Testing:"
@echo " make test - Run all tests"
@echo " make test-cover - Run tests with coverage"
@echo " make bench - Run benchmarks"
@echo " make bench-stat - Run benchmarks with statistical sampling (10x)"
@echo " make bench-compare - Compare against baseline (needs benchstat)"
@echo " make bench-save - Save current results as baseline"
@echo " make bench-check - Check for performance regressions"
@echo ""
@echo "Quality:"
@echo " make fmt - Format code"
@echo " make lint - Run linter"
@echo " make check - Format + lint + test"
@echo ""
@echo "Dependencies:"
@echo " make deps - Download dependencies"
@echo " make update-deps - Update dependencies"
@echo ""
@echo "Other:"
@echo " make install - Install to GOPATH/bin"
@echo " make clean - Clean build artifacts"
@echo ""