A complete blockchain implementation featuring: - synord: Full node with GHOSTDAG consensus - explorer-web: Modern React blockchain explorer with 3D DAG visualization - CLI wallet and tools - Smart contract SDK and example contracts (DEX, NFT, token) - WASM crypto library for browser/mobile
349 lines
9.1 KiB
Bash
Executable file
349 lines
9.1 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Synor Profiling Script
|
|
# Generates flamegraphs and performance profiles for critical paths
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
PROFILE_DIR="$PROJECT_ROOT/target/profiles"
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
|
|
|
|
# Check dependencies
|
|
check_deps() {
|
|
info "Checking profiling dependencies..."
|
|
|
|
# Check for cargo-flamegraph
|
|
if ! command -v cargo-flamegraph &> /dev/null; then
|
|
warn "cargo-flamegraph not found. Installing..."
|
|
cargo install flamegraph
|
|
fi
|
|
|
|
# Check for samply (alternative profiler)
|
|
if ! command -v samply &> /dev/null; then
|
|
warn "samply not found. Install with: cargo install samply"
|
|
fi
|
|
|
|
# macOS: check for dtrace access
|
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
if ! csrutil status 2>/dev/null | grep -q "disabled"; then
|
|
warn "On macOS, you may need to disable SIP for dtrace-based profiling"
|
|
warn "Alternative: use 'samply' which uses the Instruments profiler"
|
|
fi
|
|
fi
|
|
|
|
success "Dependencies checked"
|
|
}
|
|
|
|
# Build with profiling symbols
|
|
build_profile() {
|
|
info "Building with profiling profile..."
|
|
cd "$PROJECT_ROOT"
|
|
cargo build --profile profiling --workspace
|
|
success "Build complete"
|
|
}
|
|
|
|
# Profile kHeavyHash mining
|
|
profile_mining() {
|
|
info "Profiling kHeavyHash mining..."
|
|
mkdir -p "$PROFILE_DIR/mining"
|
|
|
|
cd "$PROJECT_ROOT"
|
|
|
|
# Run mining benchmark with flamegraph
|
|
if command -v cargo-flamegraph &> /dev/null; then
|
|
CARGO_PROFILE_BENCH_DEBUG=true cargo flamegraph \
|
|
--bench mining_bench \
|
|
-p synor-mining \
|
|
--output "$PROFILE_DIR/mining/flamegraph.svg" \
|
|
-- --bench "kheavyhash"
|
|
success "Mining flamegraph saved to $PROFILE_DIR/mining/flamegraph.svg"
|
|
else
|
|
# Fallback to regular benchmark with timing
|
|
cargo bench -p synor-mining --bench mining_bench -- --verbose
|
|
fi
|
|
}
|
|
|
|
# Profile GHOSTDAG consensus
|
|
profile_ghostdag() {
|
|
info "Profiling GHOSTDAG consensus..."
|
|
mkdir -p "$PROFILE_DIR/ghostdag"
|
|
|
|
cd "$PROJECT_ROOT"
|
|
|
|
if command -v cargo-flamegraph &> /dev/null; then
|
|
CARGO_PROFILE_BENCH_DEBUG=true cargo flamegraph \
|
|
--bench ghostdag_bench \
|
|
-p synor-dag \
|
|
--output "$PROFILE_DIR/ghostdag/flamegraph.svg" \
|
|
-- --bench
|
|
success "GHOSTDAG flamegraph saved to $PROFILE_DIR/ghostdag/flamegraph.svg"
|
|
else
|
|
cargo bench -p synor-dag --bench ghostdag_bench -- --verbose
|
|
fi
|
|
}
|
|
|
|
# Profile storage operations
|
|
profile_storage() {
|
|
info "Profiling storage operations..."
|
|
mkdir -p "$PROFILE_DIR/storage"
|
|
|
|
cd "$PROJECT_ROOT"
|
|
|
|
if command -v cargo-flamegraph &> /dev/null; then
|
|
CARGO_PROFILE_BENCH_DEBUG=true cargo flamegraph \
|
|
--bench storage_bench \
|
|
-p synor-storage \
|
|
--output "$PROFILE_DIR/storage/flamegraph.svg" \
|
|
-- --bench
|
|
success "Storage flamegraph saved to $PROFILE_DIR/storage/flamegraph.svg"
|
|
else
|
|
cargo bench -p synor-storage --bench storage_bench -- --verbose
|
|
fi
|
|
}
|
|
|
|
# Profile crypto operations
|
|
profile_crypto() {
|
|
info "Profiling crypto operations..."
|
|
mkdir -p "$PROFILE_DIR/crypto"
|
|
|
|
cd "$PROJECT_ROOT"
|
|
|
|
if command -v cargo-flamegraph &> /dev/null; then
|
|
CARGO_PROFILE_BENCH_DEBUG=true cargo flamegraph \
|
|
--bench crypto_bench \
|
|
-p synor-crypto \
|
|
--output "$PROFILE_DIR/crypto/flamegraph.svg" \
|
|
-- --bench
|
|
success "Crypto flamegraph saved to $PROFILE_DIR/crypto/flamegraph.svg"
|
|
else
|
|
cargo bench -p synor-crypto --bench crypto_bench -- --verbose
|
|
fi
|
|
}
|
|
|
|
# Profile consensus validation
|
|
profile_consensus() {
|
|
info "Profiling consensus validation..."
|
|
mkdir -p "$PROFILE_DIR/consensus"
|
|
|
|
cd "$PROJECT_ROOT"
|
|
|
|
if command -v cargo-flamegraph &> /dev/null; then
|
|
CARGO_PROFILE_BENCH_DEBUG=true cargo flamegraph \
|
|
--bench consensus_bench \
|
|
-p synor-consensus \
|
|
--output "$PROFILE_DIR/consensus/flamegraph.svg" \
|
|
-- --bench
|
|
success "Consensus flamegraph saved to $PROFILE_DIR/consensus/flamegraph.svg"
|
|
else
|
|
cargo bench -p synor-consensus --bench consensus_bench -- --verbose
|
|
fi
|
|
}
|
|
|
|
# Run all benchmarks and compare
|
|
run_all_benchmarks() {
|
|
info "Running all benchmarks..."
|
|
cd "$PROJECT_ROOT"
|
|
|
|
# Create baseline if it doesn't exist
|
|
if [[ ! -d "$PROFILE_DIR/baseline" ]]; then
|
|
info "Creating baseline benchmark results..."
|
|
cargo bench --workspace -- --save-baseline baseline
|
|
success "Baseline saved"
|
|
else
|
|
info "Comparing against baseline..."
|
|
cargo bench --workspace -- --baseline baseline
|
|
fi
|
|
}
|
|
|
|
# Profile with samply (macOS-friendly)
|
|
profile_with_samply() {
|
|
local target="$1"
|
|
|
|
if ! command -v samply &> /dev/null; then
|
|
error "samply not installed. Run: cargo install samply"
|
|
fi
|
|
|
|
info "Profiling $target with samply..."
|
|
mkdir -p "$PROFILE_DIR/samply"
|
|
|
|
cd "$PROJECT_ROOT"
|
|
|
|
case "$target" in
|
|
mining)
|
|
samply record -- cargo bench -p synor-mining --bench mining_bench
|
|
;;
|
|
ghostdag)
|
|
samply record -- cargo bench -p synor-dag --bench ghostdag_bench
|
|
;;
|
|
storage)
|
|
samply record -- cargo bench -p synor-storage --bench storage_bench
|
|
;;
|
|
crypto)
|
|
samply record -- cargo bench -p synor-crypto --bench crypto_bench
|
|
;;
|
|
consensus)
|
|
samply record -- cargo bench -p synor-consensus --bench consensus_bench
|
|
;;
|
|
*)
|
|
error "Unknown target: $target"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Generate summary report
|
|
generate_report() {
|
|
info "Generating profiling report..."
|
|
|
|
local report="$PROFILE_DIR/PROFILING_REPORT.md"
|
|
|
|
cat > "$report" << 'EOF'
|
|
# Synor Profiling Report
|
|
|
|
Generated: $(date)
|
|
|
|
## Critical Paths Analyzed
|
|
|
|
### 1. kHeavyHash Mining
|
|
- Matrix initialization time
|
|
- Hash computation throughput
|
|
- Memory allocation patterns
|
|
|
|
### 2. GHOSTDAG Consensus
|
|
- Block ordering performance
|
|
- Blue score calculation
|
|
- Merge set computation
|
|
|
|
### 3. Storage Operations
|
|
- RocksDB read/write latency
|
|
- Batch operation efficiency
|
|
- Cache hit rates
|
|
|
|
### 4. Cryptography
|
|
- Ed25519 signing/verification
|
|
- Dilithium3 operations
|
|
- Hybrid signature performance
|
|
|
|
## Flamegraphs
|
|
|
|
See SVG files in subdirectories:
|
|
- `mining/flamegraph.svg`
|
|
- `ghostdag/flamegraph.svg`
|
|
- `storage/flamegraph.svg`
|
|
- `crypto/flamegraph.svg`
|
|
- `consensus/flamegraph.svg`
|
|
|
|
## Optimization Opportunities
|
|
|
|
1. **Hot paths** - Look for wide bars at the top of flamegraphs
|
|
2. **Allocation pressure** - Search for `alloc` or `malloc` patterns
|
|
3. **Lock contention** - Look for mutex/rwlock wait times
|
|
4. **Serialization overhead** - Check borsh/serde time
|
|
|
|
## Running Profiles
|
|
|
|
```bash
|
|
# Profile specific component
|
|
./scripts/profile.sh mining
|
|
./scripts/profile.sh ghostdag
|
|
./scripts/profile.sh storage
|
|
|
|
# Run all benchmarks with comparison
|
|
./scripts/profile.sh all
|
|
|
|
# Use samply on macOS
|
|
./scripts/profile.sh samply mining
|
|
```
|
|
EOF
|
|
|
|
success "Report generated at $report"
|
|
}
|
|
|
|
# Print usage
|
|
usage() {
|
|
cat << EOF
|
|
Usage: $0 <command> [options]
|
|
|
|
Commands:
|
|
check Check profiling dependencies
|
|
build Build with profiling symbols
|
|
mining Profile kHeavyHash mining
|
|
ghostdag Profile GHOSTDAG consensus
|
|
storage Profile storage operations
|
|
crypto Profile cryptographic operations
|
|
consensus Profile consensus validation
|
|
all Run all benchmarks
|
|
samply Profile with samply (macOS-friendly)
|
|
report Generate profiling report
|
|
|
|
Options:
|
|
-h, --help Show this help message
|
|
|
|
Examples:
|
|
$0 check # Check dependencies
|
|
$0 mining # Profile mining
|
|
$0 samply ghostdag # Profile GHOSTDAG with samply
|
|
$0 all # Run all benchmarks
|
|
EOF
|
|
}
|
|
|
|
# Main entry point
|
|
main() {
|
|
case "${1:-}" in
|
|
check)
|
|
check_deps
|
|
;;
|
|
build)
|
|
build_profile
|
|
;;
|
|
mining)
|
|
check_deps
|
|
profile_mining
|
|
;;
|
|
ghostdag)
|
|
check_deps
|
|
profile_ghostdag
|
|
;;
|
|
storage)
|
|
check_deps
|
|
profile_storage
|
|
;;
|
|
crypto)
|
|
check_deps
|
|
profile_crypto
|
|
;;
|
|
consensus)
|
|
check_deps
|
|
profile_consensus
|
|
;;
|
|
all)
|
|
check_deps
|
|
run_all_benchmarks
|
|
;;
|
|
samply)
|
|
profile_with_samply "${2:-}"
|
|
;;
|
|
report)
|
|
generate_report
|
|
;;
|
|
-h|--help|"")
|
|
usage
|
|
;;
|
|
*)
|
|
error "Unknown command: $1"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
main "$@"
|