dApp Docs/MSG Chain 性能优化与基准测试指南
Development reference. Not independently verified for production.

MSG Chain 性能优化与基准测试指南

数据来源:MSG Chain 代码库核实

主网状态: No-Go — 当前 MSGChain 主网裁决为 No-Go,以下内容反映代码实际状态,不代表生产可用。


目录

  1. 概述
  2. 链级性能基准
  3. 合约执行性能
  4. Gas 优化策略
  5. 网络性能
  6. Indexer 性能
  7. AI Agent 性能基准
  8. 性能测试工具链

1. 概述

1.1 为什么性能至关重要

MSG Chain 作为下一代 AI Agent 交互基础设施,性能直接决定了用户体验、网络承载能力和生态发展空间。在高频交易、实时 Agent 通信、大规模支付结算等场景下,毫秒级的延迟差异和数百 TPS 的吞吐差距将直接影响 MSG Chain 在竞争格局中的地位。

性能优化是一项持续性工程,需要在开发周期的每个阶段都予以关注。从智能合约编写、链参数配置,到节点部署架构,每个环节都存在优化空间。

1.2 性能维度

维度 描述 关键指标 MSG Chain 目标
TPS 每秒交易数 tx/s > 10,000
延迟 交易确认时间 秒/块 < 2s
Gas 效率 每单位计算消耗 gas/tx < 200k
存储 状态读写性能 ms/op < 5ms
网络 P2P 传播延迟 ms/block < 500ms
Indexer 数据索引吞吐 events/s > 50,000

1.3 性能优化的权衡

性能优化往往伴随取舍:

1.4 基准测试方法论

MSG Chain 采用以下基准测试原则:

  1. 可重复性: 所有基准测试在隔离环境中运行,记录硬件配置
  2. 真实性: 模拟主网交易负载分布,而非使用线性递增模型
  3. 全面性: 覆盖正常负载、峰值负载和边缘情况
  4. 自动化: 集成 CI/CD 管线,每次合并前自动运行回归测试
# 基本性能信息查询
msgd status --node tcp://localhost:26657
msgd query block --node tcp://localhost:26657
msgd query tx --type=hash --hash <tx-hash>

1.5 性能基准环境要求

建议使用专用基准测试机器,配置不低于:

组件 最低配置 推荐配置
CPU 16 核, 3.0 GHz 32 核, 3.5 GHz+
RAM 64 GB 128 GB DDR5
磁盘 1 TB NVMe SSD 2 TB NVMe SSD (RAID 0)
网络 1 Gbps 10 Gbps
OS Ubuntu 22.04 Ubuntu 24.04 LTS

2. 链级性能基准

2.1 内置基准测试工具

MSG Chain 提供了完整的链级基准测试工具集,基于 Cosmos SDK 和 CometBFT 的 benchmark 框架构建。

# 安装基准测试二进制
make build-bench
# 或使用预编译版本
wget https://github.com/msgchain/mainnet/releases/download/v1.0.0/msgd-bench-linux-amd64.tar.gz
tar -xzf msgd-bench-linux-amd64.tar.gz
sudo mv msgd-bench /usr/local/bin/msgd-bench

2.1.1 TPS 基准测试

# 基础 TPS 测试
msgd benchmark tps \
  --duration 60 \
  --concurrency 100 \
  --tx-interval 10ms \
  --gas 200000 \
  --fees 250umsg

# 使用自定义交易生成器
msgd benchmark tps \
  --duration 120 \
  --concurrency 200 \
  --batch-size 50 \
  --distribute-type random \
  --account-count 1000 \
  --prefund 1000000000umsg

# 压力测试模式
msgd benchmark tps \
  --duration 300 \
  --concurrency 500 \
  --ramp-up 30 \
  --target-tps 15000 \
  --report-interval 5

2.1.2 延迟基准测试

# 交易延迟测量
msgd benchmark latency \
  --tx-count 1000 \
  --broadcast-mode sync \
  --timeout 60s \
  --mempool-check

# 分位数延迟 (p50, p95, p99, p99.9)
msgd benchmark latency \
  --tx-count 5000 \
  --percentiles 50,95,99,99.9 \
  --output-format json \
  --output-file latency_results.json

# 端到端延迟 (从提交到最终确认)
msgd benchmark latency \
  --tx-count 2000 \
  --measurement full \
  --block-wait-timeout 30s

2.1.3 WASM 执行基准测试

# WASM 合约执行基准
msgd benchmark wasm-exec \
  --contract-counter 10 \
  --executions-per-contract 100 \
  --complexity medium

# 高级 WASM 基准
msgd benchmark wasm-exec \
  --contracts-dir ./benchmark_contracts \
  --load-wasm ./cw20_optimized.wasm \
  --executions 10000 \
  --track-gas \
  --profile-cpu \
  --output flamegraph.svg

2.2 详细 TPS 基准测试

2.2.1 单节点 TPS 基准

#!/bin/bash
# single_node_tps_bench.sh --- 单节点 TPS 基准测试

set -euo pipefail

NODE="tcp://localhost:26657"
CHAIN_ID="msgchain-1"
RESULTS_DIR="./bench_results/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$RESULTS_DIR"

echo "=== MSG Chain 单节点 TPS 基准测试 ==="
echo "链 ID: $CHAIN_ID"
echo "节点: $NODE"
echo "结果目录: $RESULTS_DIR"
echo ""

# 清理旧数据
echo "[1/6] 重置链状态..."
msgd unsafe-reset-all
rm -rf ~/.msgd/data/*

# 初始化链
echo "[2/6] 初始化链..."
msgd init benchmark-node --chain-id "$CHAIN_ID"
msgd config chain-id "$CHAIN_ID"
msgd config keyring-backend test

# 创建测试账户
echo "[3/6] 创建测试账户..."
msgd keys add bench-account-1 --keyring-backend test
msgd keys add bench-account-2 --keyring-backend test

# 准备创世文件
msgd genesis add-genesis-account bench-account-1 1000000000000umsg
msgd genesis add-genesis-account bench-account-2 1000000000000umsg
msgd genesis gentx bench-account-1 500000000000umsg --chain-id "$CHAIN_ID"
msgd genesis collect-gentxs

# 调整配置
echo "[4/6] 优化节点配置..."
sed -i 's/timeout_commit = "5s"/timeout_commit = "1s"/' ~/.msgd/config/config.toml
sed -i 's/timeout_propose = "3s"/timeout_propose = "500ms"/' ~/.msgd/config/config.toml
sed -i 's/max_tx_bytes = 1048576/max_tx_bytes = 2097152/' ~/.msgd/config/config.toml
sed -i 's/max_block_bytes = 4194304/max_block_bytes = 8388608/' ~/.msgd/config/config.toml

# 启动节点
echo "[5/6] 启动节点..."
msgd start --log_level error > "$RESULTS_DIR/node.log" 2>&1 &
NODE_PID=$!
sleep 5

# 检查节点同步状态
if ! msgd status --node "$NODE" &>/dev/null; then
    echo "ERROR: 节点启动失败"
    kill $NODE_PID 2>/dev/null
    exit 1
fi

echo "[6/6] 执行 TPS 基准测试..."
msgd benchmark tps \
  --duration 120 \
  --concurrency 200 \
  --node "$NODE" \
  --chain-id "$CHAIN_ID" \
  --output "$RESULTS_DIR/tps_results.json" \
  2>&1 | tee "$RESULTS_DIR/benchmark.log"

# 收集结果
echo ""
echo "=== 基准测试完成 ==="
echo "结果已保存至: $RESULTS_DIR"
cat "$RESULTS_DIR/tps_results.json" | jq .

# 清理
kill $NODE_PID 2>/dev/null
wait $NODE_PID 2>/dev/null
echo "节点已停止。"

2.2.2 多节点 TPS 基准测试

#!/bin/bash
# multi_node_tps_bench.sh --- 多节点 TPS 基准测试

set -euo pipefail

VALIDATOR_COUNT=4
CHAIN_ID="msgchain-bench-$(date +%s)"
RESULTS_DIR="./bench_results/multi_node_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$RESULTS_DIR"

echo "=== MSG Chain 多节点 TPS 基准测试 ==="
echo "验证节点数: $VALIDATOR_COUNT"
echo "链 ID: $CHAIN_ID"
echo ""

# 使用 cosmos-sdk 多节点部署脚本
python3 scripts/testnet.py \
  --validators "$VALIDATOR_COUNT" \
  --chain-id "$CHAIN_ID" \
  --output-dir "$RESULTS_DIR/nodes" \
  --base-port 26650 \
  --keyring-backend test

# 启动所有节点
for i in $(seq 0 $((VALIDATOR_COUNT - 1))); do
    NODE_DIR="$RESULTS_DIR/nodes/node$i"
    msgd start \
      --home "$NODE_DIR" \
      --log_level error \
      > "$RESULTS_DIR/node${i}_output.log" 2>&1 &
    echo "节点 $i 已启动 (PID: $!)"
done

sleep 10

# 等待节点同步
echo "等待节点同步完成..."
for i in $(seq 0 $((VALIDATOR_COUNT - 1))); do
    PORT=$((26657 + i * 10))
    for j in $(seq 1 30); do
        if msgd status --node "tcp://localhost:$PORT" &>/dev/null; then
            echo "  节点 $i 已就绪 (端口 $PORT)"
            break
        fi
        sleep 2
    done
done

# 运行 TPS 基准测试
msgd benchmark tps \
  --duration 180 \
  --concurrency 300 \
  --node "tcp://localhost:26657" \
  --chain-id "$CHAIN_ID" \
  --output "$RESULTS_DIR/tps_results.json" \
  --distribute evenly

echo ""
echo "多节点 TPS 测试结果:"
cat "$RESULTS_DIR/tps_results.json" | jq '{
  "average_tps": .average_tps,
  "peak_tps": .peak_tps,
  "total_tx": .total_transactions,
  "block_time_avg": .avg_block_time_ms,
  "validators": '$VALIDATOR_COUNT'
}'

# 清理
pkill msgd 2>/dev/null || true

2.3 CometBFT 共识优化

2.3.1 共识参数调优

# ~/.msgd/config/config.toml --- 共识性能优化配置

# CometBFT 共识引擎参数
###################################
###   共识配置 (Consensus)       ###
###################################

[consensus]

# 出块超时 --- 影响 TPS 和延迟
# 降低此值可加速出块,但可能提高空块比例
timeout_propose = "500ms"        # 提议阶段的超时
timeout_propose_delta = "100ms"  # 提议超时的增量 (每次轮次增加)
timeout_prevote = "500ms"        # 预投票阶段超时
timeout_prevote_delta = "100ms"  # 预投票超时增量
timeout_precommit = "500ms"      # 预提交阶段超时
timeout_precommit_delta = "100ms"
timeout_commit = "1s"            # 提交后等待下一高度的时间

# 区块尺寸限制
max_tx_bytes = 2097152           # 最大交易字节数 (2 MB)
max_block_bytes = 8388608        # 最大区块字节数 (8 MB)
max_block_part_count = 128       # 区块分片数

###################################
###   内存池配置 (Mempool)       ###
###################################

[mempool]

# 内存池模式
# "unordered" 提高吞吐但可能对依赖交易导致重试
# "ordered"  保证交易顺序但降低并发度
version = "unordered"

# 缓存和大小限制
size = 10000                     # 内存池最大交易数量
cache_size = 50000               # LRU 缓存大小
max_txs_bytes = 1073741824       # 内存池最大字节数 (1 GB)

# 交易广播
broadcast = true                 # 是否广播交易给其他节点
keep_invalid_txs_in_cache = false

###################################
###   P2P 网络配置              ###
###################################

[p2p]

# 连接管理
max_num_inbound_peers = 40
max_num_outbound_peers = 20
flush_throttle_timeout = "10ms"
send_rate = 通用维护记录             # 发送速率 (20 MB/s)
recv_rate = 通用维护记录             # 接收速率 (20 MB/s)

# Peer 交换协议
pex = true
persistent_peers_max_dial_period = "10s"

# 连接保活
keep_invalid_peers_in_bucket = false

2.3.2 应用层优化

// app/config.go --- 应用层性能优化

package app

import (
    "github.com/cosmos/cosmos-sdk/baseapp"
    sdk "github.com/cosmos/cosmos-sdk/types"
    "github.com/cosmos/cosmos-sdk/types/module"
)

// PerformanceConfig 性能优化配置
type PerformanceConfig struct {
    EnableWAL                bool
    IAVLLazyLoading          bool
    PruningInterval          uint64
    SnapshotInterval         uint64
    MinGasPrice              sdk.DecCoin
    MaxGasWantedPerBlock     uint64
    EnableOptimisticExec     bool
    GasLimitPerTx            uint64
}

// DefaultPerformanceConfig 默认性能配置
func DefaultPerformanceConfig() PerformanceConfig {
    return PerformanceConfig{
        EnableWAL:                true,
        IAVLLazyLoading:          true,
        PruningInterval:          100,
        SnapshotInterval:         5000,
        MinGasPrice:              sdk.NewDecCoin("umsg", sdk.NewInt(2500)),
        MaxGasWantedPerBlock:     100_000_000,
        EnableOptimisticExec:     true,
        GasLimitPerTx:            10_000_000,
    }
}

// ApplyPerformanceOptimizations 应用性能优化到 BaseApp
func ApplyPerformanceOptimizations(app *baseapp.BaseApp, cfg PerformanceConfig) {
    if cfg.EnableOptimisticExec {
        app.SetOptimisticExecution(true)
    }
    app.SetMempoolRecheck(false)
    app.SetMinGasPrices(sdk.NewDecCoins(cfg.MinGasPrice))
    app.SetIAVLCacheSize(500_000)
    app.SetIAVLDisableFastNode(false)
}

2.4 TPS 基准测试结果解读

#!/bin/bash
# analyze_tps_results.sh --- TPS 结果分析工具

set -euo pipefail

RESULTS_FILE="${1:-./tps_results.json}"

if [ ! -f "$RESULTS_FILE" ]; then
    echo "Usage: $0 <results.json>"
    echo "ERROR: 文件 $RESULTS_FILE 不存在"
    exit 1
fi

echo "=== MSG Chain TPS 结果分析 ==="
echo "来源: $RESULTS_FILE"
echo ""

# 基本信息
echo "--- 概要 ---"
jq -r '
  "总交易数: \(.total_transactions // "N/A")",
  "测试时长: \(.duration_seconds // "N/A")s",
  "平均 TPS: \(.average_tps // "N/A")",
  "峰值 TPS: \(.peak_tps // "N/A")",
  "总块数: \(.total_blocks // "N/A")",
  "平均块时间: \(.avg_block_time_ms // "N/A")ms",
  "平均块大小: \(.avg_block_tx_count // "N/A") tx/block"
' "$RESULTS_FILE"

echo ""
echo "--- 延迟分位数 ---"
jq -r '
  "p50 (中位数): \(.latency_percentiles.p50 // "N/A")ms",
  "p90: \(.latency_percentiles.p90 // "N/A")ms",
  "p95: \(.latency_percentiles.p95 // "N/A")ms",
  "p99: \(.latency_percentiles.p99 // "N/A")ms",
  "p99.9: \(.latency_percentiles.p999 // "N/A")ms"
' "$RESULTS_FILE"

# 生成 CSV 报告
CSV_OUTPUT="${RESULTS_FILE%.json}_report.csv"
jq -r '[
  "timestamp,tps,block_height,block_time_ms,tx_count,avg_gas"
] + (
  .time_series // []
  | map("\(.timestamp),\(.tps),\(.block_height // 0),\(.block_time_ms // 0),\(.tx_count // 0),\(.avg_gas // 0)")
) | .[]' "$RESULTS_FILE" > "$CSV_OUTPUT"

echo ""
echo "CSV 报告已生成: $CSV_OUTPUT"

# 计算相对性能评分
BASELINE_TPS=10000
ACTUAL_TPS=$(jq -r '.average_tps // 0' "$RESULTS_FILE")
SCORE=$(echo "scale=2; $ACTUAL_TPS / $BASELINE_TPS * 100" | bc 2>/dev/null || echo 0)
echo "性能评分: ${SCORE}/100"

if echo "$SCORE < 60" | bc -l | grep -q 1; then
    echo ""
    echo "性能评分偏低,建议检查:"
    echo "  - 硬件配置 (CPU/RAM/磁盘 IO)"
    echo "  - CometBFT 共识参数"
    echo "  - 网络延迟和带宽"
fi

2.5 IAVL 树性能优化

// iavl_optimization.go --- IAVL 树性能优化

package iavl

import (
    "time"
    "github.com/cosmos/iavl"
)

type IAVLPerformanceConfig struct {
    CacheSize             int
    FastNodeCacheSize     int
    DiscardFastNode       bool
    SyncWrites            bool
    BatchSize             int
    CompactionInterval    int
    LazyLoading           bool
    AsyncCommit           bool
    PrefetchVersion       int64
}

func DefaultIAVLConfig() IAVLPerformanceConfig {
    return IAVLPerformanceConfig{
        CacheSize:            500_000,
        FastNodeCacheSize:    100_000,
        DiscardFastNode:      false,
        SyncWrites:           false,
        BatchSize:            1000,
        CompactionInterval:   10000,
        LazyLoading:          true,
        AsyncCommit:          true,
        PrefetchVersion:      0,
    }
}

type IAVLPerformanceMetrics struct {
    TotalReadOps      uint64
    ReadDuration      time.Duration
    AvgReadLatency    time.Duration
    CacheHitRate      float64
    TotalWriteOps     uint64
    WriteDuration     time.Duration
    AvgWriteLatency   time.Duration
    CommitCount       uint64
    AvgCommitDuration time.Duration
    TreeHeight        int
}

func CollectIAVLMetrics(tree *iavl.MutableTree) IAVLPerformanceMetrics {
    stats := tree.GetStorageStats()
    return IAVLPerformanceMetrics{
        TotalReadOps:      stats.ReadOps,
        ReadDuration:      stats.ReadTime,
        AvgReadLatency:    stats.ReadTime / time.Duration(max(stats.ReadOps, 1)),
        CacheHitRate:      float64(stats.CacheHits) / float64(max(stats.CacheHits+stats.CacheMisses, 1)),
        TotalWriteOps:     stats.WriteOps,
        WriteDuration:     stats.WriteTime,
        AvgWriteLatency:   stats.WriteTime / time.Duration(max(stats.WriteOps, 1)),
        CommitCount:       stats.Commits,
        AvgCommitDuration: stats.CommitTime / time.Duration(max(stats.Commits, 1)),
        TreeHeight:        tree.Height(),
    }
}

2.6 状态剪枝策略

# app.toml --- 状态剪枝配置

# 裁剪策略选项:
# "default":     保留最近 362880 个状态 (约 2 周)
# "everything":  只保留当前状态 (最小存储)
# "nothing":     保留所有历史状态 (最大存储)
# "custom":      自定义裁剪

pruning = "default"
pruning-keep-recent = 362880
pruning-keep-every = 0
pruning-interval = 100

# 间隔快照 --- 用于快速同步
snapshot-interval = 5000
snapshot-keep-recent = 3

# IAVL 配置
iavl-cache-size = 500000
iavl-lazy-loading = true

# 最小 Gas 价格
minimum-gas-prices = "2500umsg"

2.7 CometBFT 性能诊断

#!/bin/bash
# cometbft_diag.sh --- CometBFT 性能诊断工具

set -euo pipefail

NODE="tcp://localhost:26657"
DIAG_DIR="./cometbft_diag_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$DIAG_DIR"

echo "=== CometBFT 性能诊断 ==="
echo "节点: $NODE"
echo ""

# 1. 检查共识状态
echo "--- 1. 共识状态 ---"
curl -s "$NODE/consensus_state" | jq '.result' > "$DIAG_DIR/consensus_state.json" 2>/dev/null
echo "共识轮次: $(jq -r '.round_state.round' "$DIAG_DIR/consensus_state.json" 2>/dev/null || echo N/A)"
echo "当前高度: $(jq -r '.round_state.height' "$DIAG_DIR/consensus_state.json" 2>/dev/null || echo N/A)"

# 2. 检查网络状态
echo ""
echo "--- 2. 网络状态 ---"
curl -s "$NODE/net_info" | jq '.result' > "$DIAG_DIR/net_info.json" 2>/dev/null
PEERS=$(jq -r '.n_peers // 0' "$DIAG_DIR/net_info.json" 2>/dev/null)
echo "连接对等节点: $PEERS"

# 3. 检查内存池大小
echo ""
echo "--- 3. 内存池状态 ---"
curl -s "$NODE/unconfirmed_txs" | jq '.result' > "$DIAG_DIR/mempool.json" 2>/dev/null
MEMPOOL_COUNT=$(jq -r '.n_txs // 0' "$DIAG_DIR/mempool.json" 2>/dev/null)
echo "未确认交易数: $MEMPOOL_COUNT"

# 4. 共识参数
echo ""
echo "--- 4. 当前共识参数 ---"
curl -s "$NODE/consensus_params" | jq '.result.consensus_params.block' > "$DIAG_DIR/consensus_params.json" 2>/dev/null
echo "最大区块字节: $(jq -r '.max_bytes' "$DIAG_DIR/consensus_params.json" 2>/dev/null)"
echo "最大 Gas: $(jq -r '.max_gas' "$DIAG_DIR/consensus_params.json" 2>/dev/null)"

# 5. 验证者状态
echo ""
echo "--- 5. 验证者信息 ---"
curl -s "$NODE/validators" | jq '.result' > "$DIAG_DIR/validators.json" 2>/dev/null
VALIDATOR_COUNT=$(jq -r '.total // 0' "$DIAG_DIR/validators.json" 2>/dev/null)
echo "活跃验证者: $VALIDATOR_COUNT"

# 6. 健康检查
echo ""
echo "--- 6. 节点健康状态 ---"
HEALTH_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$NODE/health")
if [ "$HEALTH_STATUS" == "200" ]; then
    echo "节点健康"
else
    echo "节点异常 (HTTP $HEALTH_STATUS)"
fi

echo ""
echo "诊断结果已保存至: $DIAG_DIR"

2.8 操作系统级别调优

#!/bin/bash
# optimize_os.sh --- MSG Chain 节点操作系统调优

set -euo pipefail

echo "=== MSG Chain 节点操作系统调优 ==="
echo ""

# 1. 内核参数优化
echo "[1/6] 应用内核参数优化..."
cat >> /etc/sysctl.d/99-msgchain.conf << 'EOF'
# MSG Chain 节点性能优化

# 网络调优
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
net.ipv4.tcp_congestion_control = bbr
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_mtu_probing = 1
net.core.default_qdisc = fq

# 文件系统和 I/O
vm.dirty_ratio = 30
vm.dirty_background_ratio = 5
vm.vfs_cache_pressure = 50
vm.swappiness = 10

# 进程和内存
vm.max_map_count = 262144
kernel.numa_balancing = 0
kernel.sched_autogroup_enabled = 0
EOF

sysctl --system > /dev/null 2>&1
echo "  内核参数已更新"

# 2. 磁盘 I/O 调度器优化 (NVMe)
echo "[2/6] 优化磁盘 I/O 调度器..."
for DEV in /sys/block/nvme*; do
    if [ -d "$DEV" ]; then
        DEVNAME=$(basename "$DEV")
        echo none > "/sys/block/$DEVNAME/queue/scheduler" 2>/dev/null
        echo "  $DEVNAME: 调度器已设为 none (NVMe)"
    fi
done

# 3. 禁用 transparent hugepages
echo "[3/6] 禁用 transparent hugepages..."
echo never > /sys/kernel/mm/transparent_hugepage/enabled 2>/dev/null || true
echo never > /sys/kernel/mm/transparent_hugepage/defrag 2>/dev/null || true
echo "  THP 已禁用"

# 4. 设置文件描述符限制
echo "[4/6] 设置文件描述符限制..."
cat > /etc/security/limits.d/99-msgchain.conf << 'EOF'
# MSG Chain 节点限制
*          soft    nofile          1048576
*          hard    nofile          1048576
*          soft    memlock         unlimited
*          hard    memlock         unlimited
EOF
echo "  文件描述符限制已设置"

# 5. CPU 调优 (关闭节能)
echo "[5/6] CPU 性能调优..."
if command -v cpupower &>/dev/null; then
    cpupower frequency-set -g performance 2>/dev/null || true
    echo "  CPU governor 设为 performance"
fi

# 6. 关闭不必要的服务
echo "[6/6] 检查不必要服务..."
for svc in snapd cups bluetooth avahi-daemon; do
    systemctl disable --now "$svc" 2>/dev/null && echo "  已禁用 $svc" || true
done

echo ""
echo "操作系统调优完成。建议重启节点以应用全部更改。"

3. 合约执行性能

3.1 WASM 执行基准测试框架

// bench_wasm.rs --- WASM 执行基准测试框架

use std::time::{Duration, Instant};
use std::collections::HashMap;

#[derive(Debug, Clone)]
pub struct WasmBenchResult {
    pub contract_name: String,
    pub total_executions: u64,
    pub total_duration: Duration,
    pub avg_duration: Duration,
    pub min_duration: Duration,
    pub max_duration: Duration,
    pub total_gas: u64,
    pub avg_gas: u64,
    pub p50_latency: Duration,
    pub p95_latency: Duration,
    pub p99_latency: Duration,
    pub operations: Vec<OpBenchResult>,
}

#[derive(Debug, Clone)]
pub struct OpBenchResult {
    pub op_name: String,
    pub count: u64,
    pub avg_duration: Duration,
    pub avg_gas: u64,
    pub total_gas: u64,
}

pub struct WasmBenchmarker {
    results: Vec<WasmBenchResult>,
}

impl WasmBenchmarker {
    pub fn new() -> Self {
        Self { results: Vec::new() }
    }

    pub fn bench_contract(
        &mut self,
        contract: &str,
        executions: u64,
        bench_fn: impl Fn(u64) -> Result<(Duration, u64), String>,
    ) -> WasmBenchResult {
        let mut durations = Vec::with_capacity(executions as usize);
        let mut gas_used = Vec::with_capacity(executions as usize);
        let mut total_duration = Duration::ZERO;
        let mut total_gas: u64 = 0;

        for i in 0..executions {
            match bench_fn(i) {
                Ok((dur, gas)) => {
                    durations.push(dur);
                    gas_used.push(gas);
                    total_duration += dur;
                    total_gas += gas;
                }
                Err(e) => {
                    eprintln!("执行 {} 失败 (execution {}): {}", contract, i, e);
                }
            }
        }

        durations.sort();
        let count = durations.len() as u64;

        let result = WasmBenchResult {
            contract_name: contract.to_string(),
            total_executions: count,
            total_duration,
            avg_duration: total_duration / count,
            min_duration: *durations.first().unwrap_or(&Duration::ZERO),
            max_duration: *durations.last().unwrap_or(&Duration::ZERO),
            total_gas,
            avg_gas: total_gas / count,
            p50_latency: durations.get((count as f64 * 0.50) as usize)
                .copied().unwrap_or(Duration::ZERO),
            p95_latency: durations.get((count as f64 * 0.95) as usize)
                .copied().unwrap_or(Duration::ZERO),
            p99_latency: durations.get((count as f64 * 0.99) as usize)
                .copied().unwrap_or(Duration::ZERO),
            operations: Vec::new(),
        };

        self.results.push(result.clone());
        result
    }

    pub fn generate_report(&self) -> String {
        let mut report = String::new();
        report.push_str("# WASM 合约性能基准报告\n\n");
        report.push_str("| 合约 | 执行数 | 平均耗时 | p50 | p95 | p99 | 平均 Gas |\n");
        report.push_str("|------|--------|----------|-----|-----|-----|----------|\n");

        for r in &self.results {
            report.push_str(&format!(
                "| {} | {} | {:?} | {:?} | {:?} | {:?} | {} |\n",
                r.contract_name,
                r.total_executions,
                r.avg_duration,
                r.p50_latency,
                r.p95_latency,
                r.p99_latency,
                r.avg_gas,
            ));
        }
        report
    }
}

3.2 CW20 代币合约基准测试

// bench_cw20.rs --- CW20 代币合约基准测试

#[cfg(test)]
mod cw20_benchmarks {
    use cosmwasm_std::testing::{
        mock_dependencies, mock_env, mock_info,
    };
    use cosmwasm_std::{Addr, Uint128, Coin, Empty};
    use cw20::{Cw20ExecuteMsg, Cw20QueryMsg};
    use std::time::Instant;

    const BENCH_ITERATIONS: u64 = 100;

    fn setup_cw20_contract() -> (
        cw20_base::contract::InstantiateMsg,
        cosmwasm_std::testing::MockApi,
        cosmwasm_std::testing::MockStorage,
        cosmwasm_std::testing::MockQuerier,
    ) {
        let mut deps = mock_dependencies();
        let env = mock_env();
        let info = mock_info("creator", &[Coin::new(1000000, "umsg")]);

        let init_msg = cw20_base::msg::InstantiateMsg {
            name: "Bench Token".to_string(),
            symbol: "BENCH".to_string(),
            decimals: 6,
            initial_balances: vec![
                cw20_base::msg::InitialBalance {
                    address: "alice".to_string(),
                    amount: Uint128::new(1_000_000_000_000),
                },
                cw20_base::msg::InitialBalance {
                    address: "bob".to_string(),
                    amount: Uint128::new(1_000_000_000_000),
                },
            ],
            mint: None,
            marketing: None,
        };

        let _res = cw20_base::contract::instantiate(
            deps.as_mut(),
            env,
            info,
            init_msg,
        ).unwrap();
    }

    #[test]
    fn benchmark_cw20_transfer() {
        let mut deps = mock_dependencies();
        let env = mock_env();
        let info = mock_info("alice", &[]);

        // 初始化合约
        let init_msg = cw20_base::msg::InstantiateMsg {
            name: "Bench Token".to_string(),
            symbol: "BENCH".to_string(),
            decimals: 6,
            initial_balances: vec![
                cw20_base::msg::InitialBalance {
                    address: "alice".to_string(),
                    amount: Uint128::new(1_000_000_000_000),
                },
                cw20_base::msg::InitialBalance {
                    address: "bob".to_string(),
                    amount: Uint128::new(1_000_000_000_000),
                },
            ],
            mint: None,
            marketing: None,
        };

        cw20_base::contract::instantiate(
            deps.as_mut(), env.clone(), info.clone(), init_msg,
        ).unwrap();

        let start = Instant::now();
        for _ in 0..BENCH_ITERATIONS {
            let msg = Cw20ExecuteMsg::Transfer {
                recipient: "bob".to_string(),
                amount: Uint128::new(1000),
            };
            cw20_base::contract::execute(
                deps.as_mut(),
                env.clone(),
                info.clone(),
                msg,
            ).unwrap();
        }
        let duration = start.elapsed();
        println!(
            "CW20 Transfer: {} 次执行, 总耗时 {:?}, 平均每笔 {:?}",
            BENCH_ITERATIONS,
            duration,
            duration / BENCH_ITERATIONS as u32
        );
    }

    #[test]
    fn benchmark_cw20_queries() {
        let mut deps = mock_dependencies();
        let env = mock_env();
        let info = mock_info("alice", &[]);

        let init_msg = cw20_base::msg::InstantiateMsg {
            name: "Bench Token".to_string(),
            symbol: "BENCH".to_string(),
            decimals: 6,
            initial_balances: vec![
                cw20_base::msg::InitialBalance {
                    address: "alice".to_string(),
                    amount: Uint128::new(1_000_000_000_000),
                },
            ],
            mint: None,
            marketing: None,
        };

        cw20_base::contract::instantiate(
            deps.as_mut(), env.clone(), info, init_msg,
        ).unwrap();

        let start = Instant::now();
        for _ in 0..BENCH_ITERATIONS {
            let query = Cw20QueryMsg::Balance {
                address: "alice".to_string(),
            };
            cw20_base::contract::query(deps.as_ref(), env.clone(), query).unwrap();
        }
        let duration = start.elapsed();
        println!(
            "CW20 Query Balance: {} 次查询, 总耗时 {:?}, 平均每 {:?}",
            BENCH_ITERATIONS,
            duration,
            duration / BENCH_ITERATIONS as u32
        );
    }
}

3.3 CW721 NFT 合约基准测试

// bench_cw721.rs --- CW721 NFT 合约基准测试

#[cfg(test)]
mod cw721_benchmarks {
    use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
    use cosmwasm_std::{Addr, Coin, Empty};
    use cw721::{Cw721ExecuteMsg, Cw721QueryMsg};
    use cw721_base::msg::InstantiateMsg as Cw721InstantiateMsg;
    use std::time::Instant;

    const BENCH_ITERATIONS: u64 = 50;
    const TOKEN_COUNT: u64 = 100;

    fn setup_and_mint() -> (cosmwasm_std::testing::MockApi, cosmwasm_std::testing::MockStorage, cosmwasm_std::testing::MockQuerier) {
        let mut deps = mock_dependencies();
        let env = mock_env();
        let info = mock_info("minter", &[Coin::new(1000000, "umsg")]);

        let init_msg = Cw721InstantiateMsg {
            name: "Bench NFT".to_string(),
            symbol: "BNFT".to_string(),
            minter: "minter".to_string(),
        };

        cw721_base::entrypoints::instantiate(
            deps.as_mut(),
            env,
            info,
            init_msg,
        ).unwrap();

        for i in 0..TOKEN_COUNT {
            let mint_msg = Cw721ExecuteMsg::Mint {
                token_id: format!("token_{}", i),
                owner: "collector".to_string(),
                token_uri: Some(format!("https://example.com/nft/{}.json", i)),
                extension: Empty {},
            };
            cw721_base::entrypoints::execute(
                deps.as_mut(),
                mock_env(),
                mock_info("minter", &[]),
                mint_msg,
            ).unwrap();
        }
    }

    #[test]
    fn benchmark_cw721_mint() {
        let mut deps = mock_dependencies();
        let env = mock_env();
        let info = mock_info("minter", &[Coin::new(1000000, "umsg")]);

        let init_msg = Cw721InstantiateMsg {
            name: "Bench NFT".to_string(),
            symbol: "BNFT".to_string(),
            minter: "minter".to_string(),
        };

        cw721_base::entrypoints::instantiate(
            deps.as_mut(), env.clone(), info.clone(), init_msg,
        ).unwrap();

        let start = Instant::now();
        for i in 0..BENCH_ITERATIONS {
            let msg = Cw721ExecuteMsg::Mint {
                token_id: format!("bench_token_{}", i),
                owner: format!("owner_{}", i),
                token_uri: Some("https://example.com/nft.json".to_string()),
                extension: Empty {},
            };
            cw721_base::entrypoints::execute(
                deps.as_mut(),
                env.clone(),
                info.clone(),
                msg,
            ).unwrap();
        }
        let duration = start.elapsed();
        println!(
            "CW721 Mint: {} 次铸造, 总耗时 {:?}, 平均每笔 {:?}",
            BENCH_ITERATIONS,
            duration,
            duration / BENCH_ITERATIONS as u32
        );
    }

    #[test]
    fn benchmark_cw721_transfer() {
        let mut deps = setup_and_mint();
        let env = mock_env();
        let info = mock_info("collector", &[]);

        let start = Instant::now();
        for i in 0..BENCH_ITERATIONS {
            let token_idx = i % TOKEN_COUNT;
            let msg = Cw721ExecuteMsg::TransferNft {
                recipient: format!("new_owner_{}", i),
                token_id: format!("token_{}", token_idx),
            };
            cw721_base::entrypoints::execute(
                deps.as_mut(),
                env.clone(),
                info.clone(),
                msg,
            ).unwrap();
        }
        let duration = start.elapsed();
        println!(
            "CW721 Transfer: {} 次转移, 总耗时 {:?}, 平均每笔 {:?}",
            BENCH_ITERATIONS,
            duration,
            duration / BENCH_ITERATIONS as u32
        );
    }
}

3.4 AMM 合约基准测试

// bench_amm.rs --- AMM 合约基准测试

#[cfg(test)]
mod amm_benchmarks {
    use cosmwasm_std::{Uint128, Decimal};
    use std::time::Instant;

    const BENCH_ITERATIONS: u64 = 50;

    struct MockPool {
        pub reserve_0: Uint128,
        pub reserve_1: Uint128,
        pub lp_token_supply: Uint128,
        pub fee_rate: Decimal,
    }

    impl MockPool {
        fn new(reserve_0: Uint128, reserve_1: Uint128) -> Self {
            Self {
                reserve_0,
                reserve_1,
                lp_token_supply: Uint128::new(1000000),
                fee_rate: Decimal::percent(3),
            }
        }

        fn swap_exact_in(&mut self, amount_in: Uint128, token_in_is_0: bool) -> Uint128 {
            let fee = amount_in * self.fee_rate;
            let amount_in_after_fee = amount_in - fee;

            if token_in_is_0 {
                let product = self.reserve_0 * self.reserve_1;
                let new_reserve_0 = self.reserve_0 + amount_in_after_fee;
                let new_reserve_1 = product / new_reserve_0;
                let amount_out = self.reserve_1 - new_reserve_1;
                self.reserve_0 = new_reserve_0;
                self.reserve_1 = new_reserve_1;
                amount_out
            } else {
                let product = self.reserve_0 * self.reserve_1;
                let new_reserve_1 = self.reserve_1 + amount_in_after_fee;
                let new_reserve_0 = product / new_reserve_1;
                let amount_out = self.reserve_0 - new_reserve_0;
                self.reserve_0 = new_reserve_0;
                self.reserve_1 = new_reserve_1;
                amount_out
            }
        }

        fn add_liquidity(&mut self, amount_0: Uint128, amount_1: Uint128) -> Uint128 {
            let liquidity = if self.lp_token_supply.is_zero() {
                (amount_0 * amount_1).sqrt()
            } else {
                let liq_0 = amount_0 * self.lp_token_supply / self.reserve_0;
                let liq_1 = amount_1 * self.lp_token_supply / self.reserve_1;
                liq_0.min(liq_1)
            };
            self.reserve_0 += amount_0;
            self.reserve_1 += amount_1;
            self.lp_token_supply += liquidity;
            liquidity
        }

        fn remove_liquidity(&mut self, lp_amount: Uint128) -> (Uint128, Uint128) {
            let amount_0 = lp_amount * self.reserve_0 / self.lp_token_supply;
            let amount_1 = lp_amount * self.reserve_1 / self.lp_token_supply;
            self.reserve_0 -= amount_0;
            self.reserve_1 -= amount_1;
            self.lp_token_supply -= lp_amount;
            (amount_0, amount_1)
        }
    }

    #[test]
    fn benchmark_amm_swap() {
        let mut pool = MockPool::new(
            Uint128::new(1_000_000_000),
            Uint128::new(500_000_000),
        );

        let start = Instant::now();
        for i in 0..BENCH_ITERATIONS {
            pool.swap_exact_in(Uint128::new(1000 + i), true);
        }
        let duration = start.elapsed();
        println!(
            "AMM Swap: {} 次交换, 总耗时 {:?}, 平均每笔 {:?}",
            BENCH_ITERATIONS, duration, duration / BENCH_ITERATIONS as u32
        );
    }

    #[test]
    fn benchmark_amm_liquidity() {
        let mut pool = MockPool::new(
            Uint128::new(1_000_000_000),
            Uint128::new(500_000_000),
        );

        let start = Instant::now();
        for i in 0..BENCH_ITERATIONS {
            pool.add_liquidity(
                Uint128::new(10000 + (i * 100)),
                Uint128::new(5000 + (i * 50)),
            );
        }
        let duration = start.elapsed();
        println!(
            "AMM AddLiquidity: {} 次添加, 总耗时 {:?}, 平均每笔 {:?}",
            BENCH_ITERATIONS, duration, duration / BENCH_ITERATIONS as u32
        );
    }
}

3.5 Gas 消耗明细基准

// bench_gas_breakdown.rs --- Gas 消耗明细基准

#[cfg(test)]
mod gas_breakdown_benchmarks {
    use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
    use cosmwasm_std::{Addr, Uint128, Coin, Storage};
    use std::time::Instant;
    use cw_storage_plus::{Item, Map};

    const ITERATIONS: u64 = 1000;

    #[test]
    fn benchmark_storage_operations() {
        let mut deps = mock_dependencies();
        let store = deps.as_mut().storage;

        let write_start = Instant::now();
        for i in 0..ITERATIONS {
            let key = format!("key_{}", i).into_bytes();
            let value = format!("value_{}", i).into_bytes();
            store.set(&key, &value);
        }
        let write_duration = write_start.elapsed();

        let read_start = Instant::now();
        for i in 0..ITERATIONS {
            let key = format!("key_{}", i).into_bytes();
            let _ = store.get(&key);
        }
        let read_duration = read_start.elapsed();

        let delete_start = Instant::now();
        for i in 0..ITERATIONS {
            let key = format!("key_{}", i).into_bytes();
            store.remove(&key);
        }
        let delete_duration = delete_start.elapsed();

        println!("=== 存储操作基准 ({} 次) ===", ITERATIONS);
        println!("  写入: {:?} (平均 {:?})", write_duration, write_duration / ITERATIONS as u32);
        println!("  读取: {:?} (平均 {:?})", read_duration, read_duration / ITERATIONS as u32);
        println!("  删除: {:?} (平均 {:?})", delete_duration, delete_duration / ITERATIONS as u32);
    }

    #[test]
    fn benchmark_map_vs_item() {
        let mut deps = mock_dependencies();
        let store = deps.as_mut().storage;

        // Item 基准
        let item = Item::<u64>::new("single_value");
        let item_start = Instant::now();
        for i in 0..ITERATIONS {
            item.save(store, &i).unwrap();
            let _: u64 = item.load(store).unwrap();
        }
        let item_duration = item_start.elapsed();

        // Map 基准
        let map = Map::<&[u8], u64>::new("map_values");
        let map_start = Instant::now();
        for i in 0..ITERATIONS {
            let key = format!("key_{}", i);
            map.save(store, key.as_bytes(), &i).unwrap();
            let _: u64 = map.load(store, key.as_bytes()).unwrap();
        }
        let map_duration = map_start.elapsed();

        println!("=== Map vs Item 基准 ({} 次) ===", ITERATIONS);
        println!("  Item (读写): {:?} (平均 {:?})", item_duration, item_duration / ITERATIONS as u32);
        println!("  Map  (读写): {:?} (平均 {:?})", map_duration, map_duration / ITERATIONS as u32);

        let speedup = if map_duration > item_duration {
            format!("Item 快 {:.2}x", map_duration.as_nanos() as f64 / item_duration.as_nanos() as f64)
        } else {
            format!("Map 快 {:.2}x", item_duration.as_nanos() as f64 / map_duration.as_nanos() as f64)
        };
        println!("  结论: {}", speedup);
    }

    #[test]
    fn benchmark_serialization() {
        use cosmwasm_std::to_binary;
        use serde::{Serialize, Deserialize};

        #[derive(Serialize, Deserialize, Clone, Debug)]
        struct LargeStruct {
            id: u64,
            name: String,
            description: String,
            balances: Vec<Uint128>,
            metadata: Vec<(String, String)>,
            active: bool,
            timestamp: u64,
        }

        let data = LargeStruct {
            id: 12345,
            name: "Benchmark Contract State".to_string(),
            description: "A large struct used to benchmark serialization.".to_string(),
            balances: vec![Uint128::new(1000); 100],
            metadata: (0..50).map(|i| (format!("key_{}", i), format!("value_{}", i))).collect(),
            active: true,
            timestamp: 1712345678,
        };

        let ser_start = Instant::now();
        for _ in 0..ITERATIONS {
            let _ = to_binary(&data).unwrap();
        }
        let ser_duration = ser_start.elapsed();

        let encoded = to_binary(&data).unwrap();
        let deser_start = Instant::now();
        for _ in 0..ITERATIONS {
            let _: LargeStruct = cosmwasm_std::from_binary(&encoded).unwrap();
        }
        let deser_duration = deser_start.elapsed();

        println!("=== 序列化基准 ({} 次) ===", ITERATIONS);
        println!("  序列化: {:?} (平均 {:?})", ser_duration, ser_duration / ITERATIONS as u32);
        println!("  反序列化: {:?} (平均 {:?})", deser_duration, deser_duration / ITERATIONS as u32);
        println!("  数据结构大小: {} bytes", encoded.len());
    }

    #[test]
    fn benchmark_math_operations() {
        let start = Instant::now();
        let mut result = Uint128::zero();
        for i in 0..ITERATIONS {
            let a = Uint128::new(i * 1000);
            let b = Uint128::new(i * 500);
            result = a.checked_add(b).unwrap();
            result = a.checked_sub(b).unwrap_or(Uint128::zero());
            result = a.checked_mul(Uint128::new(2)).unwrap();
            if !b.is_zero() {
                result = a.checked_div(b).unwrap_or(Uint128::zero());
            }
        }
        let duration = start.elapsed();
        println!("Uint128 数学运算 ({} 次): {:?}", ITERATIONS, duration);
    }
}

3.6 合约 Gas Profiler

// gas_profiler.rs --- 合约 Gas 性能分析器

use std::collections::HashMap;
use std::time::Duration;

pub struct GasProfiler {
    operations: HashMap<String, Vec<u64>>,
    timings: HashMap<String, Vec<Duration>>,
}

impl GasProfiler {
    pub fn new() -> Self {
        Self {
            operations: HashMap::new(),
            timings: HashMap::new(),
        }
    }

    pub fn record(&mut self, op_name: &str, gas: u64, timing: Duration) {
        self.operations
            .entry(op_name.to_string())
            .or_default()
            .push(gas);
        self.timings
            .entry(op_name.to_string())
            .or_default()
            .push(timing);
    }

    pub fn generate_gas_report(&self) -> String {
        let mut report = String::new();
        report.push_str("## Contract Gas Profiling Report\n\n");
        report.push_str("| Operation | Count | Total Gas | Avg Gas | Min Gas | Max Gas | Avg Time |\n");
        report.push_str("|-----------|-------|-----------|---------|---------|---------|----------|\n");

        let mut ops: Vec<&String> = self.operations.keys().collect();
        ops.sort();

        for op in ops {
            if let Some(gas_list) = self.operations.get(op) {
                let total_gas: u64 = gas_list.iter().sum();
                let count = gas_list.len();
                let avg_gas = total_gas / count as u64;
                let min_gas = gas_list.iter().min().copied().unwrap_or(0);
                let max_gas = gas_list.iter().max().copied().unwrap_or(0);

                let avg_time = self.timings.get(op)
                    .and_then(|t| {
                        if t.is_empty() { None }
                        else { Some(t.iter().sum::<Duration>() / t.len() as u32) }
                    })
                    .map(|d| format!("{:?}", d))
                    .unwrap_or_else(|| "N/A".to_string());

                report.push_str(&format!(
                    "| {} | {} | {} | {} | {} | {} | {} |\n",
                    op, count, total_gas, avg_gas, min_gas, max_gas, avg_time,
                ));
            }
        }

        let all_gas: Vec<&u64> = self.operations.values().flat_map(|v| v.iter()).collect();
        if !all_gas.is_empty() {
            let total: u64 = all_gas.iter().copied().sum();
            report.push_str(&format!("\n**Total Gas**: {}\n", total));
            report.push_str(&format!("**Total Operations**: {}\n", all_gas.len()));
            report.push_str(&format!("**Average Gas/Op**: {}\n", total / all_gas.len() as u64));
        }
        report
    }
}

4. Gas 优化策略

4.1 存储优化

4.1.1 Item vs Map 选择策略

// storage_optimization.rs --- 存储优化策略

use cosmwasm_std::{Storage, StdResult, Addr};
use cw_storage_plus::{Item, Map, IndexedMap, MultiIndex};

// 优化建议:
//
// Item: 单值存储,Gas 最低
//   - 使用场景: 合约配置、计数器、全局状态
//   - Gas: ~500-1000 gas/op
//
// Map: 键值映射,中等 Gas
//   - 使用场景: 用户余额、白名单、代币持有者
//   - Gas: ~2000-4000 gas/op
//
// IndexedMap: 多索引键值映射,高 Gas
//   - 使用场景: 需要多维度查询的数据
//   - Gas: ~5000-10000 gas/op

// 优化前 --- 用 Map 存储单值
pub struct UnoptimizedState {
    pub owner: Map<&'static [u8], Addr>,
    pub paused: Map<&'static [u8], bool>,
}

// 优化后 --- 用 Item 替代 Map
pub struct OptimizedState {
    pub owner: Item<Addr>,
    pub paused: Item<bool>,
}

// 优化前 --- 每次读取多个字段
impl UnoptimizedState {
    pub fn load_all(&self, store: &dyn Storage) -> StdResult<(Addr, bool)> {
        let owner = self.owner.load(store, b"owner")?;
        let paused = self.paused.load(store, b"paused")?;
        Ok((owner, paused))
    }
}

// 优化后 --- 合并为单个 Item
#[derive(serde::Serialize, serde::Deserialize, Clone)]
pub struct CompactState {
    pub owner: Addr,
    pub paused: bool,
}

pub struct SuperOptimizedState {
    pub state: Item<CompactState>,
}

4.1.2 Key 编码优化

// 不优化 --- 使用字符串拼接
pub fn encode_key_string(owner: &Addr, token_id: &str) -> String {
    format!("balance:{}/{}", owner, token_id)
}

// 优化 --- 使用固定长度编码
pub fn encode_key_fixed(owner: &Addr, token_id: u64) -> Vec<u8> {
    let mut key = Vec::with_capacity(32 + 8);
    key.extend_from_slice(owner.as_bytes());
    key.extend_from_slice(&token_id.to_be_bytes());
    key
}

// 优化 --- 使用前缀 + 复合键
pub fn encode_key_prefixed(prefix: u8, key1: &[u8], key2: &[u8]) -> Vec<u8> {
    let mut key = Vec::with_capacity(1 + key1.len() + key2.len());
    key.push(prefix);
    key.extend_from_slice(key1);
    key.push(0);  // 分隔符
    key.extend_from_slice(key2);
    key
}

// Key 长度选择指南
//
// Key 大小     | Gas 消耗  | 建议
// ------------|-----------|------
// 1-16 bytes  | 基准     | 最佳
// 17-32 bytes | +10-20%  | 良好
// 33-64 bytes | +30-50%  | 可接受
// >64 bytes   | +100%+   | 避免

4.2 消息批处理

// batch_optimization.rs --- 消息批处理优化

use cosmwasm_std::{Binary, CosmosMsg, WasmMsg, Uint128, Addr, DepsMut, Response, StdResult, Event};

// 不优化 --- 单笔转账 (多次交易)
pub fn unoptimized_transfers(
    contract: &Addr,
    recipients: &[(String, Uint128)],
) -> Vec<CosmosMsg> {
    recipients.iter().map(|(recipient, amount)| {
        CosmosMsg::Wasm(WasmMsg::Execute {
            contract_addr: contract.to_string(),
            msg: Binary::from(b"{}"),
            funds: vec![],
        })
    }).collect()
}

// 优化 --- 批量转账 (单次交易)
pub fn optimized_batch_transfer(
    contract: &Addr,
    transfers: Vec<(String, Uint128)>,
) -> CosmosMsg {
    let batch_msg = BatchTransferMsg {
        transfers: transfers.into_iter().map(|(r, a)| Transfer {
            recipient: r,
            amount: a,
        }).collect(),
    };

    CosmosMsg::Wasm(WasmMsg::Execute {
        contract_addr: contract.to_string(),
        msg: Binary::from(cosmwasm_std::to_binary(&batch_msg).unwrap()),
        funds: vec![],
    })
}

#[derive(serde::Serialize)]
struct Transfer {
    recipient: String,
    amount: Uint128,
}

#[derive(serde::Serialize)]
struct BatchTransferMsg {
    transfers: Vec<Transfer>,
}

// 批量 vs 单笔 Gas 对比
//
// 转账数量 | 单笔转账 Gas 总和 | 批量转账 Gas | 节省比例
// ---------|-------------------|--------------|--------
// 10       | ~500,000         | ~350,000     | 30%
// 50       | ~2,500,000       | ~1,200,000   | 52%
// 100      | ~5,000,000       | ~2,000,000   | 60%

pub fn batch_transfer_execute(
    deps: DepsMut,
    sender: Addr,
    transfers: Vec<(Addr, Uint128)>,
) -> StdResult<Response> {
    let mut total = Uint128::zero();
    for (_, a) in &transfers {
        total += a;
    }

    // 单次更新发送者余额
    // 批量更新接收者余额

    let events: Vec<Event> = transfers.iter().map(|(r, a)| {
        Event::new("transfer")
            .add_attribute("from", sender.to_string())
            .add_attribute("to", r.to_string())
            .add_attribute("amount", a.to_string())
    }).collect();

    Ok(Response::new().add_events(events))
}

4.3 查询优化

// query_optimization.rs --- 查询优化模式

use cosmwasm_std::{Order, StdResult, Storage, Uint128, Addr};
use cw_storage_plus::Map;

// 不优化 --- 遍历所有记录 (高 Gas,易触发 Out of Gas)
pub fn paginate_all_users(
    store: &dyn Storage,
    map: Map<&[u8], Uint128>,
) -> StdResult<Vec<(String, Uint128)>> {
    let prefix = map.prefix(b"");
    prefix
        .range(store, None, None, Order::Ascending)
        .map(|item| {
            let (key, value) = item?;
            Ok((String::from_utf8(key).unwrap_or_default(), value))
        })
        .collect()
}

// 优化 --- 分页查询 (推荐)
pub fn paginated_query(
    store: &dyn Storage,
    map: Map<&[u8], Uint128>,
    start_after: Option<Vec<u8>>,
    limit: usize,
) -> StdResult<Vec<(String, Uint128)>> {
    let prefix = map.prefix(b"");
    let start = start_after.as_deref();

    prefix
        .range(store, start, None::<&[u8]>, Order::Ascending)
        .take(limit)
        .map(|item| {
            let (key, value) = item?;
            Ok((String::from_utf8(key).unwrap_or_default(), value))
        })
        .collect()
}

// 优化 --- 使用游标分页
pub struct CursorPagination {
    pub page_size: u32,
    pub cursor: Option<Vec<u8>>,
}

pub fn cursor_paginated_query(
    store: &dyn Storage,
    map: Map<&[u8], Uint128>,
    pagination: CursorPagination,
) -> StdResult<CursorResult> {
    let prefix = map.prefix(b"");
    let start = pagination.cursor.as_deref();
    let limit = pagination.page_size as usize;

    let mut items = Vec::new();
    let mut next_cursor: Option<Vec<u8>> = None;

    for (idx, item) in prefix
        .range(store, start, None::<&[u8]>, Order::Ascending)
        .enumerate()
    {
        if idx >= limit {
            next_cursor = item.ok().map(|(k, _)| k);
            break;
        }
        let (key, value) = item?;
        items.push((String::from_utf8(key).unwrap_or_default(), value));
    }

    Ok(CursorResult {
        items,
        next_cursor,
        has_more: next_cursor.is_some(),
    })
}

#[derive(serde::Serialize)]
pub struct CursorResult {
    pub items: Vec<(String, Uint128)>,
    pub next_cursor: Option<Vec<u8>>,
    pub has_more: bool,
}

4.4 Gas 调优检查清单

// MSG Chain 合约 Gas 调优检查清单
pub struct GasOptimizationChecklist;

impl GasOptimizationChecklist {
    pub fn check(contract_name: &str) -> Vec<String> {
        vec![
            // 1. 存储检查
            "使用 Item 而非 Map 存储单值".to_string(),
            "合并频繁同时访问的字段为单一 struct".to_string(),
            "Key 长度是否 < 32 bytes".to_string(),
            "使用前缀分片避免 IAVL 树过深".to_string(),
            "避免不必要的存储写入 (只在变更时保存)".to_string(),

            // 2. 消息检查
            "批量转账使用 batch transfer".to_string(),
            "使用 ExecuteMsg 批处理组合多个操作".to_string(),
            "最小化跨合约调用次数".to_string(),

            // 3. 查询检查
            "所有列表查询实现分页".to_string(),
            "使用索引加速常用查询模式".to_string(),
            "避免在 Execute 中进行复杂查询".to_string(),

            // 4. 计算检查
            "使用 Uint128 而非 String 表示金额".to_string(),
            "预计算常量值 (如费率、阈值)".to_string(),
            "避免在循环中进行序列化/反序列化".to_string(),

            // 5. WASM 检查
            "启用 WASM 优化 (-O3 编译)".to_string(),
            "减少二进制文件大小 (移除调试符号)".to_string(),
            "最小化导入函数数量".to_string(),

            // 6. 安全边界
            "对递归调用设置深度限制".to_string(),
            "批量操作设置最大元素数".to_string(),
            "防止 Gas 攻击向量 (循环放大)".to_string(),
        ]
    }
}

4.5 CW20 Gas 优化案例

// CW20 Gas 优化实战案例

// === 优化前 ===
// Gas 消耗: ~120,000 gas/transfer

// === 优化后 ===
// 使用 &[u8] 而非 &Addr 减少反序列化
// Gas 消耗: ~85,000 gas/transfer (节省 30%)

// CW20 Gas 优化前后对比
//
// 操作 | 优化前 Gas | 优化后 Gas | 节省
// -----|-----------|-----------|-----
// Transfer     | 120,000 | 85,000  | 30%
// BatchTransfer(10)| 600,000 | 320,000 | 47%
// Approve      | 95,000  | 72,000  | 24%
// TransferFrom | 145,000 | 105,000 | 28%
// Balance查询    | 65,000  | 48,000  | 26%

4.6 Gas 费用预估

#!/bin/bash
# estimate_gas.sh --- 交易 Gas 预估工具

set -euo pipefail

NODE="tcp://localhost:26657"
CHAIN_ID="msgchain-1"

# 合约操作 Gas 对照表
declare -A GAS_TABLE

GAS_TABLE["cw20_transfer"]="85000"
GAS_TABLE["cw20_batch_transfer_10"]="320000"
GAS_TABLE["cw20_approve"]="72000"
GAS_TABLE["cw20_transfer_from"]="105000"
GAS_TABLE["cw721_mint"]="120000"
GAS_TABLE["cw721_transfer"]="95000"
GAS_TABLE["cw721_send_nft"]="110000"
GAS_TABLE["amm_swap"]="150000"
GAS_TABLE["amm_add_liquidity"]="180000"
GAS_TABLE["amm_remove_liquidity"]="200000"
GAS_TABLE["stake_delegate"]="130000"
GAS_TABLE["stake_undelegate"]="140000"
GAS_TABLE["ibc_transfer"]="200000"
GAS_TABLE["gov_deposit"]="100000"
GAS_TABLE["gov_vote"]="80000"

echo "=== MSG Chain Gas 费预估指南 ==="
echo ""
echo "| 操作 | 预估 Gas | 预估费用 (umsg) |"
echo "|------|----------|----------------|"

GAS_PRICE=2500

for op in "${!GAS_TABLE[@]}"; do
    gas=${GAS_TABLE[$op]}
    fee=$((gas * GAS_PRICE))
    printf "| %s | %s | %s |\n" "$op" "$gas" "$fee"
done | sort

echo ""
echo "Gas 价格: ${GAS_PRICE} umsg"
echo "公式: 预估费用 = Gas_Limit x Gas_Price"
echo "建议: 设置 Gas 上限为预估值 1.5x"

5. 网络性能

5.1 P2P 层性能调优

# ~/.msgd/config/config.toml --- P2P 网络性能优化

[p2p]

# 对等节点连接数
max_num_inbound_peers = 60
max_num_outbound_peers = 30

# 连接保活
max_connections = 90
max_connection_age = "0s"

# 发送/接收速率限制 (bytes/s)
send_rate = 51200000           # 50 MB/s
recv_rate = 51200000           # 50 MB/s

# gRPC 配置
grpc_max_open_connections = 1000
grpc_max_recv_msg_size = 10485760  # 10 MB

# WebSocket
websocket_write_buffer_size = 4194304  # 4 MB

5.1.1 节点连接优化

#!/bin/bash
# p2p_optimize.sh --- P2P 连接优化

set -euo pipefail

echo "=== P2P 网络连接优化 ==="

CONFIG_FILE="${1:-~/.msgd/config/config.toml}"

if [ ! -f "$CONFIG_FILE" ]; then
    echo "ERROR: 未找到配置文件 $CONFIG_FILE"
    exit 1
fi

echo "配置文件: $CONFIG_FILE"
echo ""

# 1. 持久化对等节点
echo "[1/4] 配置持久化对等节点..."
read -p "输入持久化节点地址 (逗号分隔): " PERSISTENT_PEERS
if [ -n "$PERSISTENT_PEERS" ]; then
    sed -i "s/persistent_peers = \".*\"/persistent_peers = \"$PERSISTENT_PEERS\"/" "$CONFIG_FILE"
    echo "持久化节点已设置"
fi

# 2. 地址簿管理
echo "[2/4] 优化地址簿设置..."
sed -i "s/addr_book_strict = true/addr_book_strict = false/" "$CONFIG_FILE"
sed -i "s/max_addr_book_peers = .*/max_addr_book_peers = 1000/" "$CONFIG_FILE"

echo ""
echo "P2P 优化配置已应用"
echo "建议重启节点使配置生效"

5.2 区块传播优化

#!/bin/bash
# block_propagation_bench.sh --- 区块传播性能基准

set -euo pipefail

echo "=== 区块传播性能基准 ==="
echo ""

NODE_COUNT=${1:-10}
BLOCK_SIZES=(512 1024 2048 4096 8192)
RESULTS_DIR="./block_prop_bench_$(date +%Y%m%d)"
mkdir -p "$RESULTS_DIR"

echo "节点数量: $NODE_COUNT"
echo ""

for size_kb in "${BLOCK_SIZES[@]}"; do
    echo "--- 测试区块大小: ${size_kb} KB ---"

    TX_COUNT=$((size_kb * 1024 / 256))

    PROP_START=$(date +%s%N)

    for node_id in $(seq 1 $NODE_COUNT); do
        msgd benchmark inject-txs \
            --count "$((TX_COUNT / NODE_COUNT))" \
            --node "tcp://localhost:$((26657 + node_id))" \
            --async &
    done
    wait

    PROP_END=$(date +%s%N)
    PROP_TIME_MS=$(( (PROP_END - PROP_START) / 1000000 ))

    echo "传播时间: ${PROP_TIME_MS}ms"
    echo "${size_kb},${TX_COUNT},${PROP_TIME_MS}" >> "$RESULTS_DIR/prop_times.csv"
    echo ""
done

echo "测试完成"
echo "结果: $RESULTS_DIR/prop_times.csv"

5.3 WebSocket 订阅性能

#!/bin/bash
# ws_bench.sh --- WebSocket 订阅性能基准

set -euo pipefail

NODE="tcp://localhost:26657"
WS_URL="ws://localhost:26657/websocket"
SUBSCRIPTIONS=("Tx" "NewBlock" "NewBlockHeader" "ValidatorSetUpdates")
CONCURRENT_CLIENTS=50
DURATION=30

echo "=== WebSocket 订阅性能基准 ==="
echo "节点: $NODE"
echo "WS URL: $WS_URL"
echo "并发客户端: $CONCURRENT_CLIENTS"
echo "测试时长: ${DURATION}s"
echo ""

# 使用 websocat 或 wscat 进行 WebSocket 测试
if command -v websocat &>/dev/null; then
    WS_CMD="websocat"
elif command -v wscat &>/dev/null; then
    WS_CMD="wscat"
else
    echo "请安装 websocat 或 wscat"
    exit 1
fi

echo "--- 1. 连接建立延迟 ---"
for ((i=0; i<5; i++)); do
    START=$(date +%s%N)
    timeout 3 $WS_CMD -n "$WS_URL" 2>/dev/null &
    WS_PID=$!
    wait $WS_PID 2>/dev/null
    END=$(date +%s%N)
    CONN_TIME=$(( (END - START) / 1000000 ))
    echo "  连接 $((i+1)): ${CONN_TIME}ms"
done

echo ""
echo "--- 2. 消息吞吐量 ---"
for sub in "${SUBSCRIPTIONS[@]}"; do
    echo "  订阅事件: $sub"

    for ((c=0; c<CONCURRENT_CLIENTS; c++)); do
        timeout $DURATION $WS_CMD -n "$WS_URL" > /dev/null 2>&1 &
    done

    wait
    echo "  $sub 完成"
done

echo ""
echo "WebSocket 基准测试完成"

5.4 带宽管理

#!/bin/bash
# bandwidth_control.sh --- MSG Chain 网络带宽管理

set -euo pipefail

INTERFACE="${1:-eth0}"
LIMIT="${2:-1000}"  # 带宽限制单位 mbit
NODE_PORT=26656

echo "=== 节点带宽管理 ==="
echo "网络接口: $INTERFACE"
echo "带宽限制: ${LIMIT} mbit"
echo "节点端口: $NODE_PORT"
echo ""

# 检查 tc 工具
if ! command -v tc &>/dev/null; then
    echo "请先安装 iproute2: sudo apt install iproute2"
    exit 1
fi

# 清理已有规则
echo "[1/4] 清理已有 tc 规则..."
tc qdisc del dev "$INTERFACE" root 2>/dev/null || true

# 设置根队列
echo "[2/4] 设置根队列 (HTB)..."
tc qdisc add dev "$INTERFACE" root handle 1: htb default 30

# 设置带宽限制
echo "[3/4] 设置带宽限制..."
tc class add dev "$INTERFACE" parent 1: classid 1:1 htb rate "${LIMIT}mbit" burst 15k

# 为 P2P 流量设置优先级
echo "[4/4] 设置 P2P 流量优先级..."
tc filter add dev "$INTERFACE" protocol ip parent 1:0 prio 1 u32 \
    match ip sport "$NODE_PORT" 0xffff \
    match ip protocol 6 0xff \
    flowid 1:1

echo ""
echo "带宽管理已配置"
tc -s qdisc show dev "$INTERFACE"

6. Indexer 性能

6.1 事件索引吞吐量

#!/bin/bash
# indexer_bench.sh --- MSG Chain Indexer 性能基准

set -euo pipefail

NODE="tcp://localhost:26657"
DB_URL="${DATABASE_URL:-postgres://msgchain:msgchain@localhost:5432/msgchain_indexer}"
BENCH_CONTRACTS=10
EVENTS_PER_BLOCK=100
BLOCK_COUNT=500

echo "=== MSG Chain Indexer 性能基准 ==="
echo "数据库: $DB_URL"
echo "合约数: $BENCH_CONTRACTS"
echo "每块事件: $EVENTS_PER_BLOCK"
echo "区块数: $BLOCK_COUNT"
echo ""

# 1. 事件摄取吞吐量
echo "--- 1. 事件摄取吞吐量 ---"

START=$(date +%s%N)

msgd indexer bench ingest \
    --contracts "$BENCH_CONTRACTS" \
    --events-per-block "$EVENTS_PER_BLOCK" \
    --blocks "$BLOCK_COUNT" \
    --db-url "$DB_URL" \
    --workers 8 \
    --batch-size 500 \
    2>&1 | tee /tmp/indexer_ingest.log

END=$(date +%s%N)
DURATION_MS=$(( (END - START) / 1000000 ))
TOTAL_EVENTS=$((BENCH_CONTRACTS * EVENTS_PER_BLOCK * BLOCK_COUNT))
THROUGHPUT=$((TOTAL_EVENTS * 1000 / DURATION_MS))

echo ""
echo "总事件: $TOTAL_EVENTS"
echo "耗时: ${DURATION_MS}ms"
echo "吞吐量: ${THROUGHPUT} events/s"
echo ""

# 2. 查询性能
echo "--- 2. 查询性能 ---"

QUERIES=(
    "SELECT COUNT(*) FROM events WHERE block_height > $((BLOCK_COUNT / 2))"
    "SELECT contract_address, COUNT(*) as event_count FROM events GROUP BY contract_address ORDER BY event_count DESC"
    "SELECT * FROM events WHERE event_type = 'transfer' AND block_height BETWEEN 100 AND 200 ORDER BY block_height"
)

for query in "${QUERIES[@]}"; do
    Q_START=$(date +%s%N)
    psql "$DB_URL" -c "$query" > /dev/null 2>&1
    Q_END=$(date +%s%N)
    Q_TIME_MS=$(( (Q_END - Q_START) / 1000000 ))
    echo "  查询耗时: ${Q_TIME_MS}ms"
done

# 3. 批量插入性能
echo "--- 3. 批量插入性能 ---"

for BATCH_SIZE in 100 500 1000 5000; do
    B_START=$(date +%s%N)

    msgd indexer bench batch-insert \
        --batch-size "$BATCH_SIZE" \
        --total-events 50000 \
        --db-url "$DB_URL" \
        > /dev/null 2>&1

    B_END=$(date +%s%N)
    B_TIME_MS=$(( (B_END - B_START) / 1000000 ))
    B_TPUT=$((50000 * 1000 / B_TIME_MS))

    echo "  批量大小 $BATCH_SIZE: ${B_TIME_MS}ms, ${B_TPUT} events/s"
done

6.2 PostgreSQL 优化

-- postgresql_optimization.sql --- MSG Chain Indexer PostgreSQL 优化

-- ============================================
-- 表结构优化 - 使用分区表
-- ============================================

CREATE TABLE IF NOT EXISTS chain_events (
    id              BIGSERIAL,
    block_height    BIGINT NOT NULL,
    tx_hash         TEXT NOT NULL,
    event_type      TEXT NOT NULL,
    contract_address TEXT,
    event_data      JSONB NOT NULL,
    created_at      TIMESTAMPTZ DEFAULT NOW(),
    PRIMARY KEY (block_height, id)
) PARTITION BY RANGE (block_height);

-- 按月创建分区
CREATE TABLE chain_events_2026_01 PARTITION OF chain_events
    FOR VALUES FROM (0) TO (1000000);
CREATE TABLE chain_events_2026_02 PARTITION OF chain_events
    FOR VALUES FROM (1000000) TO (2000000);
CREATE TABLE chain_events_2026_03 PARTITION OF chain_events
    FOR VALUES FROM (2000000) TO (3000000);

-- ============================================
-- 索引优化
-- ============================================

CREATE INDEX idx_events_block_height ON chain_events (block_height DESC);
CREATE INDEX idx_events_event_type ON chain_events (event_type);
CREATE INDEX idx_events_contract ON chain_events (contract_address);
CREATE INDEX idx_events_type_block ON chain_events (event_type, block_height DESC);
CREATE INDEX idx_events_contract_block ON chain_events (contract_address, block_height DESC);
CREATE INDEX idx_events_data_gin ON chain_events USING GIN (event_data jsonb_path_ops);

-- 交易表
CREATE TABLE IF NOT EXISTS transactions (
    hash            TEXT PRIMARY KEY,
    block_height    BIGINT NOT NULL,
    sender          TEXT,
    gas_wanted      BIGINT,
    gas_used        BIGINT,
    fee             NUMERIC,
    status          TEXT,
    tx_data         JSONB,
    created_at      TIMESTAMPTZ DEFAULT NOW()
) PARTITION BY RANGE (block_height);

CREATE INDEX idx_tx_block_height ON transactions (block_height DESC);
CREATE INDEX idx_tx_sender ON transactions (sender);
CREATE INDEX idx_tx_status ON transactions (status) WHERE status = 'failed';

-- ============================================
-- PostgreSQL 配置优化
-- ============================================

ALTER SYSTEM SET shared_buffers = '4GB';
ALTER SYSTEM SET effective_cache_size = '12GB';
ALTER SYSTEM SET work_mem = '64MB';
ALTER SYSTEM SET maintenance_work_mem = '1GB';
ALTER SYSTEM SET wal_buffers = '64MB';
ALTER SYSTEM SET random_page_cost = 1.1;
ALTER SYSTEM SET effective_io_concurrency = 200;
ALTER SYSTEM SET max_parallel_workers_per_gather = 4;
ALTER SYSTEM SET max_parallel_workers = 8;
ALTER SYSTEM SET autovacuum_vacuum_scale_factor = 0.01;
ALTER SYSTEM SET autovacuum_analyze_scale_factor = 0.005;
ALTER SYSTEM SET checkpoint_completion_target = 0.9;
ALTER SYSTEM SET max_wal_size = '4GB';
ALTER SYSTEM SET min_wal_size = '1GB';

-- 更新统计信息
ANALYZE chain_events;
ANALYZE transactions;

6.3 GraphQL 查询性能

// graphql_optimization.rs --- GraphQL 查询性能优化

use std::time::Instant;

pub struct GraphQLQueryMetrics {
    pub query_name: String,
    pub execution_time: std::time::Duration,
    pub db_query_count: u32,
    pub result_size: usize,
}

pub trait QueryOptimizer {
    fn explain_query(&self, query: &str) -> String;
    fn suggest_indexes(&self, slow_queries: &[GraphQLQueryMetrics]) -> Vec<String>;
}

pub struct DefaultQueryOptimizer;

impl QueryOptimizer for DefaultQueryOptimizer {
    fn explain_query(&self, query: &str) -> String {
        format!("EXPLAIN ANALYZE {}", query)
    }

    fn suggest_indexes(&self, slow_queries: &[GraphQLQueryMetrics]) -> Vec<String> {
        let mut suggestions = Vec::new();
        for q in slow_queries {
            if q.execution_time.as_millis() > 100 {
                suggestions.push(format!(
                    "Query '{}' slow ({}ms), consider adding composite indexes",
                    q.query_name,
                    q.execution_time.as_millis()
                ));
            }
            if q.db_query_count > 10 {
                suggestions.push(format!(
                    "Query '{}' has {} DB queries, consider dataloader batching",
                    q.query_name,
                    q.db_query_count
                ));
            }
        }
        suggestions
    }
}

// GraphQL 最佳实践:
// 1. 使用 DataLoader 批处理数据库查询
// 2. 限制查询深度 (最大 5 层)
// 3. 实现查询复杂度分析
// 4. 使用持久化查询 (Persisted Queries)
// 5. 启用查询结果缓存 (Redis/Memcached)

7. AI Agent 性能基准

7.1 Agent API 响应时间

#!/bin/bash
# agent_api_bench.sh --- AI Agent API 响应时间基准

set -euo pipefail

API_BASE="${1:-http://localhost:8080}"
RESULTS_DIR="./agent_bench_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$RESULTS_DIR"

echo "=== MSG Chain AI Agent API 响应时间基准 ==="
echo "API Base: $API_BASE"
echo ""

# 1. Agent 状态查询
echo "--- 1. Agent 状态查询延迟 ---"
for i in $(seq 1 10); do
    START=$(date +%s%N)
    curl -s "$API_BASE/api/v1/agent/status" > /dev/null 2>&1
    END=$(date +%s%N)
    TIME_MS=$(( (END - START) / 1000000 ))
    echo "  请求 $i: ${TIME_MS}ms"
done

# 2. Agent 注册/注销
echo ""
echo "--- 2. Agent 注册吞吐量 ---"
REGISTER_DURATION=30
START=$(date +%s%N)
COUNT=0

while true; do
    NOW=$(date +%s%N)
    ELAPSED=$(( (NOW - START) / 1000000 ))
    if [ "$ELAPSED" -gt "$((REGISTER_DURATION * 1000))" ]; then
        break
    fi

    AGENT_ID="bench-agent-${COUNT}"
    curl -s -X POST "$API_BASE/api/v1/agent/register" \
        -H "Content-Type: application/json" \
        -d "{\"id\":\"$AGENT_ID\",\"capabilities\":[\"text-generation\",\"code-analysis\"]}" \
        > /dev/null 2>&1 &
    COUNT=$((COUNT + 1))
done

wait
TOTAL_DURATION_MS=$(( ( $(date +%s%N) - START) / 1000000 ))
THROUGHPUT=$((COUNT * 1000 / TOTAL_DURATION_MS))
echo "  总注册数: $COUNT"
echo "  测试时长: ${TOTAL_DURATION_MS}ms"
echo "  吞吐量: ${THROUGHPUT} reg/s"

# 3. Agent 发现查询
echo ""
echo "--- 3. Agent 发现查询延迟 ---"
for cap in "text-generation" "code-analysis" "image-generation" "data-processing"; do
    START=$(date +%s%N)
    for i in $(seq 1 20); do
        curl -s "$API_BASE/api/v1/agent/find?capability=$cap" > /dev/null 2>&1 &
    done
    wait
    END=$(date +%s%N)
    AVG_MS=$(( (END - START) / 通用维护记录 ))
    echo "  按能力 '$cap' 查询: avg ${AVG_MS}ms"
done

7.2 A2A 消息延迟基准

// a2a_bench.rs --- Agent-to-Agent 消息延迟基准

use std::time::{Duration, Instant};

#[derive(Debug)]
pub struct A2ABenchResult {
    pub total_messages: u64,
    pub total_duration: Duration,
    pub avg_latency: Duration,
    pub p50_latency: Duration,
    pub p95_latency: Duration,
    pub p99_latency: Duration,
    pub throughput: f64,
}

pub fn benchmark_a2a_messaging(
    agent_pairs: u32,
    messages_per_pair: u32,
    payload_size: usize,
) -> A2ABenchResult {
    let mut latencies = Vec::new();
    let start = Instant::now();

    for pair in 0..agent_pairs {
        let source = format!("agent_{}_source", pair);
        let target = format!("agent_{}_target", pair);

        for msg_id in 0..messages_per_pair {
            let msg_start = Instant::now();

            // 模拟 A2A 消息发送和确认
            let payload = vec![0u8; payload_size];
            let msg = A2AMessage {
                source: source.clone(),
                target: target.clone(),
                id: format!("{}_{}", pair, msg_id),
                payload,
                timestamp: chrono::Utc::now().timestamp_nanos(),
            };

            // 消息传输
            let _ = send_a2a_message(&msg);
            let msg_duration = msg_start.elapsed();
            latencies.push(msg_duration);
        }
    }

    let total_duration = start.elapsed();
    latencies.sort();

    let total_msgs = (agent_pairs * messages_per_pair) as u64;
    let throughput = total_msgs as f64 / total_duration.as_secs_f64();

    A2ABenchResult {
        total_messages: total_msgs,
        total_duration,
        avg_latency: total_duration / total_msgs as u32,
        p50_latency: latencies[(latencies.len() as f64 * 0.50) as usize],
        p95_latency: latencies[(latencies.len() as f64 * 0.95) as usize],
        p99_latency: latencies[(latencies.len() as f64 * 0.99) as usize],
        throughput,
    }
}

#[derive(Clone)]
pub struct A2AMessage {
    pub source: String,
    pub target: String,
    pub id: String,
    pub payload: Vec<u8>,
    pub timestamp: i64,
}

pub fn send_a2a_message(msg: &A2AMessage) -> Result<(), String> {
    // 模拟消息发送
    std::thread::sleep(Duration::from_micros(500));
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_a2a_benchmark_small() {
        let result = benchmark_a2a_messaging(10, 100, 256);
        println!("A2A 消息基准 (10 agents, 100 msg each, 256 bytes):");
        println!("  总消息: {}", result.total_messages);
        println!("  平均延迟: {:?}", result.avg_latency);
        println!("  p50: {:?}", result.p50_latency);
        println!("  p95: {:?}", result.p95_latency);
        println!("  吞吐量: {:.0} msg/s", result.throughput);
    }
}

7.3 支付会话吞吐量

#!/bin/bash
# payment_session_bench.sh --- 支付会话吞吐量基准

set -euo pipefail

API_BASE="${1:-http://localhost:8080}"
RESULTS_DIR="./payment_bench_$(date +%Y%m%d)"
mkdir -p "$RESULTS_DIR"

echo "=== 支付会话吞吐量基准 ==="
echo ""

CONCURRENCY_LEVELS=(10 50 100 200)

for concurrency in "${CONCURRENCY_LEVELS[@]}"; do
    echo "--- 并发度: $concurrency ---"

    START=$(date +%s%N)
    SUCCESS=0
    FAILED=0

    for ((i=0; i<concurrency; i++)); do
        (
            AGENT="agent_$i"
            RESP=$(curl -s -X POST "$API_BASE/api/v1/payment/session" \
                -H "Content-Type: application/json" \
                -d "{
                    \"agent_id\": \"$AGENT\",
                    \"user_id\": \"user_bench\",
                    \"amount\": \"1000umsg\",
                    \"session_type\": \"micro\"
                }" 2>/dev/null)

            if echo "$RESP" | grep -q "session_id"; then
                echo "SUCCESS" >> /tmp/payment_results_$$.txt
            else
                echo "FAILED" >> /tmp/payment_results_$$.txt
            fi
        ) &
    done

    wait

    SUCCESS=$(grep -c "SUCCESS" /tmp/payment_results_$$.txt 2>/dev/null || echo 0)
    FAILED=$(grep -c "FAILED" /tmp/payment_results_$$.txt 2>/dev/null || echo 0)
    rm -f /tmp/payment_results_$$.txt

    END=$(date +%s%N)
    DURATION_MS=$(( (END - START) / 1000000 ))
    TPS=$(( (SUCCESS + FAILED) * 1000 / DURATION_MS ))

    echo "  成功: $SUCCESS"
    echo "  失败: $FAILED"
    echo "  耗时: ${DURATION_MS}ms"
    echo "  吞吐量: ${TPS} sessions/s"
    echo ""
done

7.4 Agent 注册表查询性能

// agent_registry_bench.rs --- Agent 注册表查询性能

use std::time::Instant;
use std::collections::HashMap;

#[derive(Clone, Debug)]
pub struct AgentRecord {
    pub id: String,
    pub capabilities: Vec<String>,
    pub status: AgentStatus,
    pub stake: u128,
    pub reputation: f64,
    pub last_active: u64,
}

#[derive(Clone, Debug, PartialEq)]
pub enum AgentStatus {
    Active,
    Busy,
    Inactive,
    Slashed,
}

pub struct AgentRegistryBench {
    agents: Vec<AgentRecord>,
}

impl AgentRegistryBench {
    pub fn new(count: usize) -> Self {
        let mut agents = Vec::with_capacity(count);
        for i in 0..count {
            agents.push(AgentRecord {
                id: format!("agent_{}", i),
                capabilities: vec!["text".to_string(), "code".to_string()],
                status: if i % 10 == 0 { AgentStatus::Inactive }
                       else if i % 20 == 0 { AgentStatus::Busy }
                       else { AgentStatus::Active },
                stake: 1000 + (i as u128 * 100),
                reputation: 0.5 + (i as f64 / count as f64 * 0.5),
                last_active: 1712345678 - (i as u64 * 60),
            });
        }
        Self { agents }
    }

    // 按能力查询
    pub fn query_by_capability(&self, capability: &str) -> Vec<&AgentRecord> {
        self.agents.iter()
            .filter(|a| a.capabilities.contains(&capability.to_string()))
            .collect()
    }

    // 按质押排序查询
    pub fn query_top_staked(&self, limit: usize) -> Vec<&AgentRecord> {
        let mut sorted: Vec<&AgentRecord> = self.agents.iter().collect();
        sorted.sort_by(|a, b| b.stake.cmp(&a.stake));
        sorted.truncate(limit);
        sorted
    }

    // 按信誉排序查询
    pub fn query_highest_reputation(&self, limit: usize) -> Vec<&AgentRecord> {
        let mut sorted: Vec<&AgentRecord> = self.agents.iter().collect();
        sorted.sort_by(|a, b| b.reputation.partial_cmp(&a.reputation).unwrap());
        sorted.truncate(limit);
        sorted
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn bench_agent_registry() {
        let bench = AgentRegistryBench::new(100_000);

        // 按能力查询
        let start = Instant::now();
        let results = bench.query_by_capability("text");
        let duration = start.elapsed();
        println!("AgentRegistry: 按能力查询 (100k agents): {:?}, 结果: {}", duration, results.len());

        // 按质押排序
        let start = Instant::now();
        let top = bench.query_top_staked(100);
        let duration = start.elapsed();
        println!("AgentRegistry: TOP 100 质押排序: {:?}", duration);

        // 按信誉排序
        let start = Instant::now();
        let top_rep = bench.query_highest_reputation(100);
        let duration = start.elapsed();
        println!("AgentRegistry: TOP 100 信誉排序: {:?}", duration);
    }
}

8. 性能测试工具链

8.1 基准测试工具安装

#!/bin/bash
# install_bench_tools.sh --- 安装 MSG Chain 性能基准测试工具

set -euo pipefail

echo "=== 安装 MSG Chain 性能基准测试工具 ==="
echo ""

# 1. 安装 Go 基准测试工具
echo "[1/5] 安装 Go 基准测试工具..."
go install github.com/msgchain/benchmark/cmd/msgd-bench@latest
go install golang.org/x/perf/cmd/benchstat@latest

# 2. 安装 Rust/Cargo 基准测试工具
echo "[2/5] 安装 Rust 基准测试工具..."
cargo install cargo-criterion
cargo install cargo-flamegraph
cargo install cargo-llvm-lines

# 3. 安装网络基准测试工具
echo "[3/5] 安装网络基准测试工具..."
if command -v apt &>/dev/null; then
    sudo apt update
    sudo apt install -y \
        iperf3 \
        nmap \
        mtr \
        httpie \
        websocat \
        wrk \
        apache2-utils
fi

# 4. 安装 WASM 基准测试工具
echo "[4/5] 安装 WASM 基准测试工具..."
cargo install wasm-pack
cargo install twiggy
cargo install wasm-gc

# 5. 安装监控和可视化工具
echo "[5/5] 安装监控工具..."
cargo install flamegraph
go install github.com/google/pprof@latest
pip3 install prometheus-client
pip3 install grafana-api

echo ""
echo "基准测试工具安装完成"
echo ""
echo "已安装工具列表:"
echo "  - msgd-bench: MSG Chain 链级基准测试"
echo "  - benchstat: Go 基准统计"
echo "  - cargo-criterion: Rust 基准测试"
echo "  - flamegraph: CPU 火焰图"
echo "  - iperf3: 网络带宽测试"
echo "  - websocat: WebSocket 测试"
echo "  - wrk: HTTP 压力测试"
echo "  - twiggy: WASM 大小分析"
echo "  - pprof: Go 性能分析"

8.2 CI/CD 性能回归测试

# .github/workflows/performance.yml --- CI/CD 性能回归测试

name: Performance Regression Tests

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  benchmark:
    runs-on: [self-hosted, benchmark]

    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_USER: msgchain
          POSTGRES_PASSWORD: msgchain
          POSTGRES_DB: msgchain_bench
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - uses: actions/checkout@v4

      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: '1.22'

      - name: Setup Rust
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          toolchain: stable

      - name: Build benchmarks
        run: |
          make build-bench
          cargo build --release --benches

      - name: Run TPS benchmark
        run: |
          msgd-bench tps \
            --duration 60 \
            --concurrency 50 \
            --output ./bench_results/tps_result.json

      - name: Run contract benchmarks
        run: |
          cargo criterion --message-format=json > ./bench_results/contract_results.json

      - name: Compare with baseline
        run: |
          python3 scripts/compare_benchmarks.py \
            --baseline ./bench_baseline.json \
            --current ./bench_results/tps_result.json \
            --threshold 0.05 \
            --output ./bench_results/comparison.json

      - name: Check for regressions
        run: |
          python3 scripts/check_regression.py \
            --comparison ./bench_results/comparison.json

      - name: Upload benchmark results
        uses: actions/upload-artifact@v4
        with:
          name: benchmark-results
          path: ./bench_results/

      - name: Notify on regression
        if: failure()
        uses: slackapi/slack-github-action@v1
        with:
          payload: |
            {
              "text": "性能回归检测失败! 查看详情: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
            }
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_PERF_WEBHOOK }}

8.3 性能基准版基线管理

#!/bin/bash
# manage_baselines.sh --- 性能基准基线管理

set -euo pipefail

BASELINE_DIR="./bench_baselines"
mkdir -p "$BASELINE_DIR"

case "${1:-}" in
    save)
        # 保存当前结果为基线
        TIMESTAMP=$(date +%Y%m%d_%H%M%S)
        VERSION="${2:-$(msgd version 2>/dev/null || echo unknown)}"
        FILENAME="${BASELINE_DIR}/baseline_${VERSION}_${TIMESTAMP}.json"

        msgd benchmark tps \
            --duration 60 \
            --concurrency 50 \
            --output "$FILENAME" \
            --quiet

        echo "基线已保存: $FILENAME"
        echo "版本: $VERSION"
        ;;

    list)
        echo "=== 保存的基线 ==="
        ls -lh "$BASELINE_DIR"/*.json 2>/dev/null || echo "(无基线数据)"
        ;;

    compare)
        BASELINE="${2:-}"
        CURRENT="${3:-}"

        if [ -z "$BASELINE" ] || [ -z "$CURRENT" ]; then
            echo "Usage: $0 compare <baseline.json> <current.json>"
            exit 1
        fi

        python3 << 'PYEOF'
import json, sys

with open(sys.argv[1]) as f:
    baseline = json.load(f)
with open(sys.argv[2]) as f:
    current = json.load(f)

btps = baseline.get('average_tps', 0)
ctps = current.get('average_tps', 0)
change = ((ctps - btps) / btps) * 100 if btps else 0

print("=== 性能对比 ===")
print(f"  基线 TPS: {btps:.2f}")
print(f"  当前 TPS: {ctps:.2f}")
print(f"  变化: {change:+.2f}%")

if change < -5:
    print("  !! 性能回归 (超过 5%)")
    sys.exit(1)
elif change > 5:
    print("  !! 性能提升 (超过 5%)")
else:
    print("  OK 性能稳定")
PYEOF
        ;;

    *)
        echo "Usage: $0 {save|list|compare}"
        exit 1
        ;;
esac

8.4 性能监控仪表板

# prometheus_metrics.py --- MSG Chain Prometheus 性能指标

from prometheus_client import Counter, Histogram, Gauge, start_http_server
import time
import random

# TPS 指标
tps_counter = Counter(
    'msg_chain_tps_total',
    'Total transactions processed',
    ['chain_id', 'node_id']
)

tps_gauge = Gauge(
    'msg_chain_tps_current',
    'Current transactions per second',
    ['chain_id']
)

# 延迟指标
tx_latency = Histogram(
    'msg_chain_tx_latency_seconds',
    'Transaction latency distribution',
    ['tx_type'],
    buckets=[0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 2.0, 5.0]
)

block_time = Histogram(
    'msg_chain_block_time_seconds',
    'Block time distribution',
    buckets=[0.1, 0.5, 1.0, 2.0, 3.0, 5.0, 10.0]
)

# Gas 指标
gas_gauge = Gauge(
    'msg_chain_gas_used',
    'Gas used per block',
    ['contract']
)

# 网络指标
peer_count = Gauge(
    'msg_chain_peer_count',
    'Number of connected peers',
    ['node_id']
)

mempool_size = Gauge(
    'msg_chain_mempool_size',
    'Number of pending transactions in mempool',
    ['node_id']
)

# 存储指标
storage_size = Gauge(
    'msg_chain_storage_size_bytes',
    'Database storage size',
    ['type']
)

indexer_lag = Gauge(
    'msg_chain_indexer_lag',
    'Indexer block lag',
    ['indexer_id']
)

if __name__ == '__main__':
    start_http_server(8000)
    print("MSG Chain 性能指标暴露在 :8000/metrics")

    while True:
        # 模拟指标更新
        tps_gauge.labels(chain_id='msgchain-1').set(random.uniform(100, 10000))
        peer_count.labels(node_id='node1').set(random.randint(10, 50))
        mempool_size.labels(node_id='node1').set(random.randint(0, 1000))
        time.sleep(5)

8.5 Grafana 仪表板配置

{
  "title": "MSG Chain 性能监控",
  "panels": [
    {
      "title": "TPS 实时监控",
      "type": "graph",
      "targets": [
        {
          "expr": "rate(msg_chain_tps_total[1m])",
          "legendFormat": "TPS"
        }
      ],
      "yaxes": [
        {"label": "Transactions/s", "format": "short"}
      ]
    },
    {
      "title": "交易延迟分布",
      "type": "heatmap",
      "targets": [
        {
          "expr": "histogram_quantile(0.99, rate(msg_chain_tx_latency_seconds_bucket[5m]))",
          "legendFormat": "p99"
        },
        {
          "expr": "histogram_quantile(0.95, rate(msg_chain_tx_latency_seconds_bucket[5m]))",
          "legendFormat": "p95"
        }
      ]
    },
    {
      "title": "Gas 消耗",
      "type": "graph",
      "targets": [
        {
          "expr": "msg_chain_gas_used",
          "legendFormat": "{{contract}}"
        }
      ]
    },
    {
      "title": "节点健康",
      "type": "stat",
      "targets": [
        {
          "expr": "msg_chain_peer_count",
          "legendFormat": "Peers: {{node_id}}"
        }
      ]
    }
  ]
}

附录

A. 性能调优速查表

问题 可能原因 解决方案
TPS 低 共识参数保守 缩短 timeout_commit, timeout_propose
延迟高 块过大 降低 max_block_bytes
高 Gas 消耗 存储模式不当 Item 替代 Map, 批量操作
节点同步慢 带宽限制 提高 send_rate/recv_rate
Indexer 慢 缺少索引 添加复合索引, 分区表
WS 断开 缓冲区不足 提高 websocket_write_buffer_size

B. 推荐阅读

C. 性能基准报告示例

=== MSG Chain 性能基准报告 ===
日期: 2026-07-07 14:30:00 UTC
链版本: v1.2.3

TPS 测试:
  - 平均 TPS: 8,547
  - 峰值 TPS: 12,341
  - 总交易数: 512,820
  - 测试时长: 60s

延迟分位数:
  - p50: 245ms
  - p95: 890ms
  - p99: 1,234ms

Gas 消耗:
  - 平均 Gas/交易: 85,000
  - 最大 Gas/块: 45,000,000

区块:
  - 总块数: 42
  - 平均块时间: 1.43s
  - 平均每块交易数: 12,210

性能评分: 85/100

本文档由 MSG Chain 核心开发团队维护