Files
volt-vmm/benchmarks/pps.sh
Karl Clinger 40ed108dd5 Volt VMM (Neutron Stardust): source-available under AGPSL v5.0
KVM-based microVMM for the Volt platform:
- Sub-second VM boot times
- Minimal memory footprint
- Landlock LSM + seccomp security
- Virtio device support
- Custom kernel management

Copyright (c) Armored Gates LLC. All rights reserved.
Licensed under AGPSL v5.0
2026-03-21 01:04:35 -05:00

174 lines
5.9 KiB
Bash
Executable File

#!/bin/bash
# Volt Network Benchmark - Packets Per Second Tests
# Tests small packet performance (best indicator of CPU overhead)
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Parse arguments
SERVER_IP="${1:?Usage: $0 <server-ip> [backend-name] [duration]}"
BACKEND="${2:-unknown}"
DURATION="${3:-30}"
# Setup results directory
TIMESTAMP=$(date +%Y-%m-%d_%H%M%S)
RESULTS_DIR="${SCRIPT_DIR}/results/${BACKEND}/${TIMESTAMP}"
mkdir -p "$RESULTS_DIR"
echo "=== Volt PPS Benchmark ==="
echo "Server: $SERVER_IP"
echo "Backend: $BACKEND"
echo "Duration: ${DURATION}s per test"
echo "Results: $RESULTS_DIR"
echo ""
echo "Note: Small packet tests show virtualization overhead best"
echo ""
# Function to format large numbers
format_number() {
local num="$1"
if [ -z "$num" ] || [ "$num" = "N/A" ]; then
echo "N/A"
elif (( $(echo "$num >= 1000000" | bc -l 2>/dev/null || echo 0) )); then
printf "%.2fM" $(echo "$num / 1000000" | bc -l)
elif (( $(echo "$num >= 1000" | bc -l 2>/dev/null || echo 0) )); then
printf "%.2fK" $(echo "$num / 1000" | bc -l)
else
printf "%.0f" "$num"
fi
}
# UDP Small Packet Tests with iperf3
echo "--- UDP Small Packet Tests (iperf3) ---"
echo ""
for pkt_size in 64 128 256 512; do
echo "[$(date +%H:%M:%S)] Testing ${pkt_size}-byte UDP packets..."
output_file="${RESULTS_DIR}/udp-${pkt_size}byte.json"
# -l sets UDP payload size, actual packet = payload + 28 (IP+UDP headers)
# -b 0 = unlimited bandwidth (find max PPS)
if iperf3 -c "$SERVER_IP" -u -l "$pkt_size" -b 0 -t "$DURATION" -J > "$output_file" 2>&1; then
if command -v jq &> /dev/null && [ -f "$output_file" ]; then
packets=$(jq -r '.end.sum.packets // 0' "$output_file" 2>/dev/null)
pps=$(echo "scale=0; $packets / $DURATION" | bc 2>/dev/null || echo "N/A")
bps=$(jq -r '.end.sum.bits_per_second // 0' "$output_file" 2>/dev/null)
mbps=$(echo "scale=2; $bps / 1000000" | bc 2>/dev/null || echo "N/A")
loss=$(jq -r '.end.sum.lost_percent // 0' "$output_file" 2>/dev/null)
printf " %4d bytes: %12s pps (%s Mbps, loss: %.2f%%)\n" \
"$pkt_size" "$(format_number $pps)" "$mbps" "$loss"
else
echo " ${pkt_size} bytes: Complete (see JSON)"
fi
else
echo " ${pkt_size} bytes: FAILED"
fi
sleep 2
done
echo ""
# TCP Request/Response with netperf (best for measuring transaction rate)
echo "--- TCP Transaction Tests (netperf) ---"
echo ""
if command -v netperf &> /dev/null; then
# TCP_RR - Request/Response (simulates real application traffic)
echo "[$(date +%H:%M:%S)] Running TCP_RR (request/response)..."
output_file="${RESULTS_DIR}/tcp-rr.txt"
if netperf -H "$SERVER_IP" -l "$DURATION" -t TCP_RR > "$output_file" 2>&1; then
# Extract transactions per second
tps=$(tail -1 "$output_file" | awk '{print $NF}')
echo " TCP_RR: $(format_number $tps) trans/sec"
echo "TCP_RR_TPS=$tps" > "${RESULTS_DIR}/tcp-rr.env"
else
echo " TCP_RR: FAILED (is netserver running?)"
fi
sleep 2
# TCP_CRR - Connect/Request/Response (includes connection setup overhead)
echo "[$(date +%H:%M:%S)] Running TCP_CRR (connect/request/response)..."
output_file="${RESULTS_DIR}/tcp-crr.txt"
if netperf -H "$SERVER_IP" -l "$DURATION" -t TCP_CRR > "$output_file" 2>&1; then
tps=$(tail -1 "$output_file" | awk '{print $NF}')
echo " TCP_CRR: $(format_number $tps) trans/sec"
echo "TCP_CRR_TPS=$tps" > "${RESULTS_DIR}/tcp-crr.env"
else
echo " TCP_CRR: FAILED"
fi
sleep 2
# UDP_RR - UDP Request/Response
echo "[$(date +%H:%M:%S)] Running UDP_RR (request/response)..."
output_file="${RESULTS_DIR}/udp-rr.txt"
if netperf -H "$SERVER_IP" -l "$DURATION" -t UDP_RR > "$output_file" 2>&1; then
tps=$(tail -1 "$output_file" | awk '{print $NF}')
echo " UDP_RR: $(format_number $tps) trans/sec"
echo "UDP_RR_TPS=$tps" > "${RESULTS_DIR}/udp-rr.env"
else
echo " UDP_RR: FAILED"
fi
else
echo "netperf not installed - skipping transaction tests"
echo "Run ./setup.sh to install"
fi
echo ""
# Generate summary
echo "=== PPS Summary ==="
SUMMARY_FILE="${RESULTS_DIR}/pps-summary.txt"
{
echo "Volt PPS Benchmark Results"
echo "================================"
echo "Backend: $BACKEND"
echo "Server: $SERVER_IP"
echo "Date: $(date)"
echo "Duration: ${DURATION}s per test"
echo ""
echo "UDP Packet Rates:"
echo "-----------------"
for pkt_size in 64 128 256 512; do
json_file="${RESULTS_DIR}/udp-${pkt_size}byte.json"
if [ -f "$json_file" ] && command -v jq &> /dev/null; then
packets=$(jq -r '.end.sum.packets // 0' "$json_file" 2>/dev/null)
pps=$(echo "scale=0; $packets / $DURATION" | bc 2>/dev/null || echo "N/A")
loss=$(jq -r '.end.sum.lost_percent // 0' "$json_file" 2>/dev/null)
printf " %4d bytes: %12s pps (loss: %.2f%%)\n" "$pkt_size" "$(format_number $pps)" "$loss"
fi
done
echo ""
echo "Transaction Rates:"
echo "------------------"
for test in tcp-rr tcp-crr udp-rr; do
env_file="${RESULTS_DIR}/${test}.env"
if [ -f "$env_file" ]; then
source "$env_file"
case "$test" in
tcp-rr) val="$TCP_RR_TPS" ;;
tcp-crr) val="$TCP_CRR_TPS" ;;
udp-rr) val="$UDP_RR_TPS" ;;
esac
printf " %-10s %12s trans/sec\n" "${test}:" "$(format_number $val)"
fi
done
} | tee "$SUMMARY_FILE"
echo ""
echo "Full results saved to: $RESULTS_DIR"
echo ""
echo "Key Insight: 64-byte PPS shows raw packet processing overhead."
echo "Higher PPS = lower virtualization overhead = better performance."