Skip to content

Performance

Optimizing blockchain node performance is crucial for maintaining network participation, reducing operational costs, and ensuring reliable RPC services. Blockchain nodes are resource-intensive applications that require careful tuning of memory, CPU, storage, and network parameters. This chapter provides comprehensive guidance on optimizing node performance across different hardware configurations and use cases.


Blockchain nodes have complex memory requirements:

┌─────────────────────────────────────────────────────────────┐
│ GETH MEMORY USAGE BREAKDOWN │
├─────────────────────────────────────────────────────────────┤
│ │
│ Total Memory: 16-64 GB │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Heap Memory │ │
│ │ ┌───────────┬───────────────┬───────────────┐ │ │
│ │ │ State │ Cache │ Trie Cache │ │ │
│ │ │ (EVM) │ (Blocks) │ (Merkle) │ │ │
│ │ │ ~4GB │ ~2GB │ ~2GB │ │ │
│ │ └───────────┴───────────────┴───────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Off-Heap Memory │ │
│ │ ┌───────────┬───────────────┬───────────────┐ │ │
│ │ │ LevelDB │ MDBX │ Snapshots │ │ │
│ │ │ Cache │ Cache │ (Read-Only) │ │ │
│ │ │ ~4GB │ ~4GB │ ~8GB │ │ │
│ │ └───────────┴───────────────┴───────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Terminal window
# Cache size in megabytes
# Default: 4096 MB (4 GB)
# For 16GB RAM system
geth --cache 4096
# For 32GB RAM system
geth --cache 8192
# For 64GB RAM system
geth --cache 16384
# For high-performance servers
geth --cache 32768
# View cache statistics
geth attach http://localhost:8545
> debug.getBlockChainInfo()
System RAMCacheGC SettingsNotes
8 GB2048DefaultMinimal configuration
16 GB4096DefaultStandard configuration
32 GB8192GOGC=200Good performance
64 GB16384GOGC=300High performance
128 GB32768GOGC=400Maximum performance
Terminal window
# High-memory configuration
export GOGC=300
export GOMEMLIMIT=32GiB
geth \
--cache 16384 \
--cache.database 8192 \
--cache.trie 4096 \
--cache.snapshot 4096
Terminal window
# Monitor memory usage
watch -n 5 'free -h'
# Detailed process memory
ps aux | grep geth
# Memory over time
pmap -x $(pgrep geth) | tail -1
# Check for memory leaks
journalctl -u geth | grep -i "memory"
journalctl -u geth | grep -i "gc"
# Using gotop (if installed)
gotop

┌─────────────────────────────────────────────────────────────┐
│ CPU OPTIMIZATION STRATEGY │
├─────────────────────────────────────────────────────────────┤
│ │
│ Blockchain Workload: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 40% - Cryptographic operations (hashing) │ │
│ │ 30% - Database I/O (LevelDB/RocksDB) │ │
│ │ 20% - Network processing │ │
│ │ 10% - State trie processing │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ Recommendations: │
│ ✓ High single-thread performance is critical │
│ ✓ More cores help with parallel processing │
│ ✓ AVX2/AVX-512 instructions for crypto │
│ ✓ ECC RAM for stability │
│ │
└─────────────────────────────────────────────────────────────┘
Terminal window
# Limit CPU usage (useful for shared servers)
taskset -c 0-3 geth --syncmode snap
# View available cores
nproc
# Check CPU flags for crypto support
grep -o 'avx[0-9]*' /proc/cpuinfo | head -1
# Disable hyperthreading (sometimes helps)
# In BIOS, or via:
tuna --cores=0-7 geth
Terminal window
# Set GOMAXPROCS to number of cores
export GOMAXPROCS=16
# Set GOMAXPROCS dynamically
# In systemd service:
Environment=GOMAXPROCS=16
# Or programmatically:
geth --gcmode=archive --exec "GOMAXPROCS=16"

Node TypeStorageGrowth/Year
Full Node~1.2 TB~100 GB
Archive Node~12 TB~500 GB
Pruned Node~400 GB~100 GB
Storage TypeRead IOPSWrite IOPSNotes
HDD100100Not recommended
SATA SSD50,00020,000Testnet only
NVMe SSD500,000+300,000+Required for production
NVMe (Gen4)700,000+500,000+Optimal
Terminal window
# Check current partition alignment
blockdev --report
# For NVMe, ensure 4K alignment
sudo fdisk -l /dev/nvme0n1
Terminal window
# Use ext4 or XFS (not BTRFS for database)
# Format with optimal settings
sudo mkfs.ext4 -E stride=128,stripe-width=128 /dev/nvme0n1
# Mount with noatime for better performance
# /etc/fstab:
# /dev/nvme0n1 /data ext4 defaults,noatime,nodiratime,discard 0 2
Terminal window
# Geth automatically tunes LevelDB
# But you can override:
# Cache for LevelDB
geth --cache 8192
# Number of open files
geth --cache.fdlimit 1024
Terminal window
# Erigon with RocksDB tuning
erigon \
--db.size.limit=3TB \
--db.allow_unfastiate_geth=true \
--prune.mode=minimal \
--private.api.addr=localhost:9090
Terminal window
# Check disk I/O
iostat -x 5
# Check disk usage
df -h
# Check I/O wait (high = bottleneck)
vmstat 1
# Monitor disk queue
iostat -x 1 | grep -E "Device|vd[a-z]"
# Benchmark storage
fio --name=random_read --ioengine=libaio --iodepth=32 \
--bs=4k --size=1G --numjobs=4 --runtime=30 \
--readonly --filename=/tmp/fio_test

Node TypeMin BandwidthRecommended
Light Node10 Mbps100 Mbps
Full Node50 Mbps1 Gbps
Archive Node100 Mbps10 Gbps
Validator100 Mbps1 Gbps
Terminal window
# Increase file descriptors
echo "* soft nofile 65536" | sudo tee -a /etc/security/limits.conf
echo "* hard nofile 65536" | sudo tee -a /etc/security/limits.conf
# For running user:
echo "$USER soft nofile 65536" | sudo tee -a /etc/security/limits.conf
echo "$USER hard nofile 65536" | sudo tee -a /etc/security/limits.conf
# Increase network buffers
sudo sysctl -w net.core.rmem_max=16777216
sudo sysctl -w net.core.wmem_max=16777216
# Persist settings
echo "net.core.rmem_max=16777216" | sudo tee -a /etc/sysctl.conf
echo "net.core.wmem_max=16777216" | sudo tee -a /etc/sysctl.conf
Terminal window
# Increase max peers
geth --maxpeers 100
# Adjust dial metrics
geth --nat extip:YOUR_PUBLIC_IP
# Enable P2P metrics
geth --pprof --pprofaddr localhost

[Unit]
Description=Ethereum Geth Node
After=network.target
[Service]
Type=simple
User=ethereum
WorkingDirectory=/home/ethereum
ExecStart=/usr/local/bin/geth \
--mainnet \
--syncmode snap \
--cache 16384 \
--cache.database 8192 \
--cache.trie 4096 \
--cache.snapshot 4096 \
--maxpeers 100 \
--http \
--http.addr 0.0.0.0 \
--http.port 8545 \
--http.api eth,net,web3,debug,txpool \
--http.vhosts "*" \
--http.corsdomain "*" \
--ws \
--ws.addr 0.0.0.0 \
--ws.port 8546 \
--ws.api eth,net,web3 \
--ws.origins "*" \
--datadir /data/ethereum \
--keydir /data/ethereum/keystore \
--allow-insecure-unlock \
--rpc.gascap 50000000 \
--rpc.txfeecap 100 \
--ws.txfeecap 10 \
--pprof \
--pprofaddr localhost \
--pprofport 6060
# Memory limits
MemoryMax=64G
MemoryHigh=48G
# CPU limits
CPUAffinity=0-15
# Restart settings
Restart=on-failure
RestartSec=5s
StandardOutput=append:/var/log/geth/output.log
StandardError=append:/var/log/geth/error.log
[Install]
WantedBy=multi-user.target
optimize_node.sh
#!/bin/bash
echo "=== Ethereum Node Performance Optimization ==="
# 1. Set kernel parameters
echo "Configuring kernel parameters..."
cat >> /etc/sysctl.conf << EOF
# Network optimizations
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
# File descriptor limits
fs.file-max=65536
# Blockchain specific
vm.max_map_count=1048576
EOF
sysctl -p
# 2. Set resource limits
echo "Configuring resource limits..."
cat >> /etc/security/limits.conf << EOF
* soft nofile 65536
* hard nofile 65536
* soft memlock unlimited
* hard memlock unlimited
EOF
# 3. CPU governor
echo "Setting CPU governor..."
for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
echo performance > $cpu
done
# 4. Disable transparent huge pages
echo "Disabling transparent huge pages..."
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
# 5. Set IO scheduler (for SSDs)
echo "Setting IO scheduler..."
for disk in /sys/block/sd*/queue/scheduler; do
echo none > $disk
done
echo "=== Optimization Complete ==="
echo "Please restart your node for changes to take effect"

MetricGoodWarningCritical
CPU Usage< 60%60-80%> 80%
Memory Usage< 70%70-85%> 85%
Disk I/O Wait< 10%10-20%> 20%
Network InStableVariableDropping
Peer Count> 105-10< 5
# node_exporter config for system metrics
scrape_configs:
- job_name: 'node'
static_configs:
- targets: ['localhost:9100']
- job_name: 'geth'
static_configs:
- targets: ['localhost:6060']

Create a dashboard with these key queries:

# CPU Usage
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# Memory Usage
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100
# Disk I/O
rate(node_disk_read_bytes_total[5m])
rate(node_disk_written_bytes_total[5m])
# Network Traffic
rate(node_network_receive_bytes_total{device="eth0"}[5m])
rate(node_network_transmit_bytes_total{device="eth0"}[5m])
# Geth sync progress
ethereum_block_height / ethereum_network_block * 100

Terminal window
# Check memory consumption
ps aux --sort=-%mem | head -10
# Check for memory leaks
journalctl -u geth | grep -i "out of memory"
# Reduce cache if needed
geth --cache 4096
Terminal window
# Find process using most CPU
top -o %CPU
# Check for runaway goroutines
curl http://localhost:6060/debug/pprof/goroutine?debug=1
# Reduce sync activity
geth --syncmode full
Terminal window
# Check I/O wait
iostat -x 1
# Find I/O heavy processes
iotop
# Consider upgrading to NVMe
lsblk -d -o NAME,TYPE,ROTA

  • Memory: Allocate appropriate cache based on available RAM (typically 50-75% of available memory)
  • CPU: Prioritize single-thread performance; more cores help with parallelism
  • Storage: NVMe SSDs are mandatory for production nodes
  • Network: Ensure adequate bandwidth and configure file descriptor limits
  • Monitoring: Track key metrics and set up alerts for degradation
  • Tuning: Use the comprehensive configuration examples provided for your hardware
  • Optimization: Run the optimization script for system-level improvements

In Chapter 48: Network Connectivity Issues, we’ll explore network troubleshooting.


Last Updated: 2026-02-22