Git钩子脚本如何检查性能问题

wen 实用脚本 1

本文目录导读:

Git钩子脚本如何检查性能问题

  1. 基础性能检查脚本结构
  2. 特定语言性能检查函数
  3. 通用性能检查
  4. 完整的 pre-commit 钩子
  5. 性能检查工具集成
  6. 性能检查报告生成
  7. 使用建议

Git 钩子脚本可以从多个维度检查代码性能问题,以下是针对不同场景的完整实现方案:

基础性能检查脚本结构

pre-commit 钩子示例(检查提交前代码)

#!/bin/bash
# .git/hooks/pre-commit
echo "🔍 开始性能检查..."
# 设置严格模式
set -e
# 定义性能违规函数
performance_violations=0
check_performance() {
    local file="$1"
    # 根据不同文件类型检查
    case "$file" in
        *.py)
            check_python_performance "$file"
            ;;
        *.js|*.ts)
            check_javascript_performance "$file"
            ;;
        *.java)
            check_java_performance "$file"
            ;;
        *.sql)
            check_sql_performance "$file"
            ;;
    esac
}

特定语言性能检查函数

Python 性能检查

check_python_performance() {
    local file="$1"
    # 检查循环中不必要的计算
    if grep -n "for.*in range\|while.*:" "$file" | grep -q "len("; then
        echo "⚠️  $file: 循环中可能重复计算 len(),建议缓存"
        ((performance_violations++))
    fi
    # 检查重复的数据库查询
    if grep -n "\.query\|\.filter\|\.get(" "$file" | grep -q "for\|while"; then
        echo "⚠️  $file: 循环中存在数据库查询,考虑批量操作"
        ((performance_violations++))
    fi
    # 检查大量字符串拼接
    if grep -n "+=.*str\|+=.*'" "$file" | head -5 | grep -q "for\|while"; then
        echo "⚠️  $file: 循环中使用字符串拼接,建议使用 join()"
        ((performance_violations++))
    fi
    # 检查未使用的导入
    local unused_imports=$(grep "^import\|^from" "$file" | while read line; do
        local module=$(echo "$line" | awk '{print $2}')
        if ! grep -q "$module" <(grep -v "^import\|^from" "$file"); then
            echo "$module"
        fi
    done)
    if [ -n "$unused_imports" ]; then
        echo "⚠️  $file: 可能未使用的导入: $unused_imports"
        ((performance_violations++))
    fi
}

JavaScript/TypeScript 性能检查

check_javascript_performance() {
    local file="$1"
    # 检查不必要的 DOM 操作
    if grep -n "\.innerHTML\s*=" "$file" | grep -q "for\|while\|forEach"; then
        echo "⚠️  $file: 循环中频繁操作 innerHTML,建议使用 DocumentFragment"
        ((performance_violations++))
    fi
    # 检查闭包中的大对象
    if grep -n "return function\|=> {" "$file" | head -10 | while read line; do
        if echo "$line" | grep -q "large\|big\|heavy"; then
            echo "⚠️  $file: 闭包中可能包含大对象,注意内存泄漏"
            ((performance_violations++))
        fi
    done
    # 检查防抖/节流使用
    if grep -n "\.addEventListener\|onclick\|onscroll\|onresize" "$file" | grep -v "debounce\|throttle"; then
        echo "⚠️  $file: 高频事件未使用防抖/节流"
        ((performance_violations++))
    fi
    # 检查 import 大小(需要 webpack 配置)
    if command -v node &> /dev/null; then
        node -e "
        const fs = require('fs');
        const content = fs.readFileSync('$file', 'utf8');
        const imports = content.match(/import\s+.*from\s+['\"]([^'\"]+)['\"]/g);
        if (imports) {
            imports.forEach(imp => {
                if (imp.includes('lodash') || imp.includes('moment')) {
                    console.log('⚠️  考虑使用 lodash 按需引入或 moment 替代方案');
                }
            });
        }
        "
    fi
}

Java 性能检查

check_java_performance() {
    local file="$1"
    # 检查 StringBuilder 使用
    if grep -n "String\s\+\w\+\s*=" "$file" | grep -q "for\|while"; then
        echo "⚠️  $file: 循环中使用字符串拼接,建议使用 StringBuilder"
        ((performance_violations++))
    fi
    # 检查大对象序列化
    if grep -n "implements Serializable\|@Serial" "$file" | grep -q "List\|Map\|Set"; then
        echo "⚠️  $file: 大集合类实现 Serializable,注意性能影响"
        ((performance_violations++))
    fi
    # 检查线程安全
    if grep -n "synchronized\|Lock\|Atomic" "$file" | grep -q "get\|set\|add\|remove"; then
        # 这里的逻辑可能需要调整
        true
    fi
    # 检查深拷贝
    if grep -n "clone()\|new.*(.*old\|deepCopy\|deepClone" "$file"; then
        echo "⚠️  $file: 使用深拷贝,注意性能开销"
        ((performance_violations++))
    fi
}

SQL 性能检查

check_sql_performance() {
    local file="$1"
    # 检查 SELECT *
    if grep -n "SELECT\s+\*" "$file"; then
        echo "⚠️  $file: 使用 SELECT *,建议明确指定列"
        ((performance_violations++))
    fi
    # 检查缺少索引的 JOIN
    if grep -n "JOIN\|LEFT JOIN\|RIGHT JOIN" "$file" | grep -v "INDEX\|index"; then
        echo "⚠️  $file: JOIN 操作可能缺少索引"
        ((performance_violations++))
    fi
    # 检查 LIKE 前导通配符
    if grep -n "LIKE\s+'%" "$file"; then
        echo "⚠️  $file: LIKE 前导通配符将导致全表扫描"
        ((performance_violations++))
    fi
    # 检查 OR 条件(可能导致索引失效)
    if grep -n "OR" "$file"; then
        echo "⚠️  $file: 使用 OR 条件可能导致索引失效"
        ((performance_violations++))
    fi
}

通用性能检查

大文件检查

check_file_size() {
    local file="$1"
    local max_size=500000  # 500KB
    if [ -f "$file" ]; then
        local size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
        if [ "$size" -gt "$max_size" ]; then
            echo "⚠️  文件过大 ($(echo "scale=2; $size/1024/1024" | bc) MB): $file"
            ((performance_violations++))
        fi
    fi
}

依赖检查(package.json)

check_dependencies() {
    if [ -f "package.json" ]; then
        local heavy_packages=("lodash" "moment" "jquery" "bootstrap")
        for package in "${heavy_packages[@]}"; do
            if grep -q "\"$package\"" "package.json"; then
                echo "⚠️  package.json 包含重依赖: $package"
                ((performance_violations++))
            fi
        done
    fi
}

完整的 pre-commit 钩子

#!/bin/bash
# .git/hooks/pre-commit
echo "🔍 开始性能检查..."
performance_violations=0
# 获取暂存的文件
staged_files=$(git diff --cached --name-only --diff-filter=ACM)
if [ -z "$staged_files" ]; then
    echo "✅ 没有需要检查的文件"
    exit 0
fi
echo "检查以下文件:"
echo "$staged_files"
echo ""
# 逐个检查文件
for file in $staged_files; do
    # 跳过非代码文件
    [[ "$file" =~ \.(md|txt|json|yml|yaml)$ ]] && continue
    echo "检查: $file"
    # 文件大小检查
    check_file_size "$file"
    # 语言特定检查
    check_performance "$file"
    echo ""
done
# 依赖检查
check_dependencies
# 输出结果
if [ "$performance_violations" -gt 0 ]; then
    echo "❌ 发现 $performance_violations 个潜在性能问题"
    echo "请修复后重新提交,或使用 git commit --no-verify 跳过检查"
    exit 1
else
    echo "✅ 性能检查通过"
    exit 0
fi

性能检查工具集成

集成 ESLint 性能规则

# .eslintrc.json 配置
{
  "rules": {
    "no-unused-vars": "error",
    "no-console": "warn",
    "no-await-in-loop": "warn",
    "require-atomic-updates": "warn"
  }
}

集成 Python Pylint 性能检查

# .pylintrc 配置
[MESSAGES CONTROL]
enable=performance
disable=C,R,W
# 在钩子中调用
if [ "$file" == *.py ]; then
    pylint --load-plugins=pylint.extensions.bad_builtin "$file" 2>/dev/null || true
fi

性能检查报告生成

generate_performance_report() {
    local report_file="performance_report_$(date +%Y%m%d_%H%M%S).md"
    cat > "$report_file" << EOF
# 性能检查报告
生成时间: $(date)
提交者: $(git config user.name)
分支: $(git branch --show-current)
## 发现的问题
EOF
    # 追加检查结果
    for violation in "${violations[@]}"; do
        echo "- $violation" >> "$report_file"
    done
    echo "报告已生成: $report_file"
}

使用建议

  1. 性能阈值设置:根据项目实际需求调整阈值
  2. 忽略列表:创建 .performanceignore 文件跳过特定检查
  3. 增量检查:只检查新修改的代码,避免全量检查
  4. 并行执行:对于大型项目,考虑并行执行检查
  5. 持续优化:定期更新检查规则,适应项目演变

将这个脚本保存为 .git/hooks/pre-commit 并赋予执行权限:

chmod +x .git/hooks/pre-commit

这种方式的性能检查可以有效预防常见的性能问题,但建议配合专业的性能分析工具使用,以获得更全面的性能保障。

抱歉,评论功能暂时关闭!