Performance Benchmarks & Stress Testing
Performance requirements, benchmarks, and stress testing standards for production DeFi
LP-9020: Performance Benchmarks & Stress Testing
Abstract
This LP defines performance requirements, benchmarking standards, and stress testing methodologies for Lux DeFi infrastructure. Ensures protocols can handle billions in daily volume with consistent performance.
Motivation
Production DeFi requires:
- Predictable performance under load
- Capacity planning for growth
- Stress testing for edge cases
- Performance regression detection
- SLA compliance verification
Specification
1. Performance Requirements
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
interface IPerformanceRequirements {
struct LatencyRequirements {
uint256 p50LatencyMs; // Median latency
uint256 p95LatencyMs; // 95th percentile
uint256 p99LatencyMs; // 99th percentile
uint256 maxLatencyMs; // Maximum allowed
}
struct ThroughputRequirements {
uint256 minTPS; // Minimum TPS
uint256 targetTPS; // Target TPS
uint256 burstTPS; // Burst capacity
uint256 sustainedMinutes; // Sustained duration
}
struct CapacityRequirements {
uint256 maxConcurrentUsers;
uint256 maxOrdersPerSecond;
uint256 maxPositions;
uint256 maxPendingOrders;
}
}
2. Benchmark Standards
| Component | Metric | Minimum | Target | Exceptional |
|---|---|---|---|---|
| DEX Engine | ||||
| Order Placement | Latency | < 50ms | < 20ms | < 5ms |
| Order Matching | Throughput | 10K/s | 100K/s | 1M/s |
| Price Updates | Latency | < 100ms | < 50ms | < 10ms |
| Oracle | ||||
| Price Fetch | Latency | < 200ms | < 100ms | < 50ms |
| Aggregation | Latency | < 500ms | < 200ms | < 100ms |
| Update Frequency | Rate | 1/min | 1/sec | 100/sec |
| Bridge | ||||
| Message Delivery | Latency | < 30s | < 10s | < 3s |
| Finality | Time | < 60s | < 30s | < 10s |
| Throughput | TPS | 100 | 1,000 | 10,000 |
| Smart Contracts | ||||
| Swap Execution | Gas | 250K | 150K | 100K |
| Complex Route | Gas | 500K | 300K | 200K |
| Batch Operations | Gas/op | 50K | 30K | 20K |
All engine figures are measured against the implementation's benchmark suite, not asserted. Prior fabricated headline numbers (e.g. "434M/581M orders per second") MUST NOT be propagated; cite the harness instead.
2a. DEX Receipt-Settlement Benchmarks (LP-9999)
The DEX splits matching (D-Chain dexvm) from settlement (C-Chain 0x9999
precompile, LP-9999). The two
layers are benchmarked separately, and end-to-end as a pipeline:
| Stage | Metric | Day-1 target | Source |
|---|---|---|---|
| D-Chain match | p50 latency / shard | < 1 ms | measured; see benchmark suite |
| D-Chain match | p99 latency / shard | < 10 ms | measured; see benchmark suite |
| C-Chain verify | BLS root verification | once per batch (amortized over all receipts in the batch) | measured; see benchmark suite |
| C-Chain settle | parallel settlement | Block-STM, fine-grained keys, no global hot slots (LP-1024) | measured; see benchmark suite |
| End-to-end | p50 (order → settled) | within a few fast blocks | measured; see benchmark suite |
The D-validator quorum signs a receipt root per block/batch, so a single BLS aggregate verification amortizes over every receipt in the batch — verification cost is independent of per-receipt throughput. Real throughput numbers live with the harness, not in this LP.
3. Stress Testing Framework
// Stress test configuration
interface StressTestConfig {
// Load parameters
initialUsers: number;
maxUsers: number;
rampUpDuration: number; // seconds
sustainDuration: number;
rampDownDuration: number;
// Operation mix
operationMix: {
swaps: number; // percentage
deposits: number;
withdrawals: number;
limitOrders: number;
cancellations: number;
};
// Thresholds
errorRateThreshold: number;
latencyP99Threshold: number;
throughputMinimum: number;
// Scenarios
scenarios: StressScenario[];
}
interface StressScenario {
name: string;
description: string;
loadPattern: 'constant' | 'ramp' | 'spike' | 'wave';
duration: number;
intensity: number;
assertions: Assertion[];
}
// Example scenarios
const stressScenarios: StressScenario[] = [
{
name: 'sustained_load',
description: 'Sustained high load for capacity testing',
loadPattern: 'constant',
duration: 3600, // 1 hour
intensity: 0.8, // 80% of max capacity
assertions: [
{ metric: 'error_rate', operator: 'lt', value: 0.001 },
{ metric: 'p99_latency', operator: 'lt', value: 500 },
{ metric: 'throughput', operator: 'gt', value: 10000 },
],
},
{
name: 'spike_test',
description: 'Sudden traffic spike simulation',
loadPattern: 'spike',
duration: 300, // 5 minutes
intensity: 2.0, // 200% of normal
assertions: [
{ metric: 'error_rate', operator: 'lt', value: 0.01 },
{ metric: 'recovery_time', operator: 'lt', value: 30 },
],
},
{
name: 'endurance_test',
description: 'Long-running stability test',
loadPattern: 'constant',
duration: 86400, // 24 hours
intensity: 0.5,
assertions: [
{ metric: 'memory_growth', operator: 'lt', value: 0.1 },
{ metric: 'error_rate', operator: 'lt', value: 0.0001 },
],
},
{
name: 'chaos_test',
description: 'Failure injection and recovery',
loadPattern: 'wave',
duration: 1800,
intensity: 0.7,
assertions: [
{ metric: 'failover_time', operator: 'lt', value: 5 },
{ metric: 'data_integrity', operator: 'eq', value: 1.0 },
],
},
];
4. Load Testing Tools
# load_test.py - Load testing framework
import asyncio
import aiohttp
import time
from dataclasses import dataclass
from typing import List, Dict
import statistics
@dataclass
class LoadTestResult:
total_requests: int
successful_requests: int
failed_requests: int
avg_latency_ms: float
p50_latency_ms: float
p95_latency_ms: float
p99_latency_ms: float
max_latency_ms: float
throughput_rps: float
error_rate: float
duration_seconds: float
class DeFiLoadTester:
def __init__(self, endpoint: str, max_concurrent: int = 1000):
self.endpoint = endpoint
self.max_concurrent = max_concurrent
self.latencies: List[float] = []
self.errors: int = 0
self.successes: int = 0
async def execute_swap(self, session: aiohttp.ClientSession) -> float:
"""Execute a swap and return latency in ms"""
start = time.perf_counter()
try:
async with session.post(
f"{self.endpoint}/swap",
json={
"tokenIn": "0x...",
"tokenOut": "0x...",
"amountIn": "1000000000000000000",
"slippage": 50,
}
) as response:
if response.status == 200:
self.successes += 1
else:
self.errors += 1
except Exception:
self.errors += 1
latency = (time.perf_counter() - start) * 1000
self.latencies.append(latency)
return latency
async def run_load_test(
self,
duration_seconds: int,
target_rps: int
) -> LoadTestResult:
"""Run load test with specified parameters"""
connector = aiohttp.TCPConnector(limit=self.max_concurrent)
async with aiohttp.ClientSession(connector=connector) as session:
start_time = time.time()
tasks = []
while time.time() - start_time < duration_seconds:
# Spawn requests to maintain target RPS
batch_size = min(target_rps, 100)
for _ in range(batch_size):
tasks.append(asyncio.create_task(
self.execute_swap(session)
))
await asyncio.sleep(1.0 / (target_rps / batch_size))
# Wait for remaining tasks
await asyncio.gather(*tasks, return_exceptions=True)
# Calculate results
sorted_latencies = sorted(self.latencies)
total = len(self.latencies)
return LoadTestResult(
total_requests=total,
successful_requests=self.successes,
failed_requests=self.errors,
avg_latency_ms=statistics.mean(self.latencies),
p50_latency_ms=sorted_latencies[int(total * 0.5)],
p95_latency_ms=sorted_latencies[int(total * 0.95)],
p99_latency_ms=sorted_latencies[int(total * 0.99)],
max_latency_ms=max(self.latencies),
throughput_rps=total / duration_seconds,
error_rate=self.errors / total,
duration_seconds=duration_seconds,
)
5. Gas Optimization Benchmarks
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract GasBenchmarks {
// Target gas costs for common operations
uint256 constant TARGET_SIMPLE_SWAP = 100_000;
uint256 constant TARGET_MULTI_HOP_SWAP = 200_000;
uint256 constant TARGET_ADD_LIQUIDITY = 150_000;
uint256 constant TARGET_REMOVE_LIQUIDITY = 120_000;
uint256 constant TARGET_PLACE_ORDER = 80_000;
uint256 constant TARGET_CANCEL_ORDER = 50_000;
uint256 constant TARGET_BATCH_SWAP = 50_000; // per swap in batch
struct GasReport {
string operation;
uint256 gasUsed;
uint256 gasTarget;
bool passedTarget;
uint256 percentOfTarget;
}
GasReport[] public gasReports;
function benchmarkSwap(
address router,
address tokenIn,
address tokenOut,
uint256 amountIn
) external returns (GasReport memory) {
uint256 gasBefore = gasleft();
// Execute swap
IRouter(router).swap(tokenIn, tokenOut, amountIn, 0, address(this));
uint256 gasUsed = gasBefore - gasleft();
GasReport memory report = GasReport({
operation: "simple_swap",
gasUsed: gasUsed,
gasTarget: TARGET_SIMPLE_SWAP,
passedTarget: gasUsed <= TARGET_SIMPLE_SWAP,
percentOfTarget: (gasUsed * 100) / TARGET_SIMPLE_SWAP
});
gasReports.push(report);
return report;
}
function runFullBenchmark(address router) external returns (GasReport[] memory) {
// Run comprehensive benchmark suite
// Returns array of all gas reports
return gasReports;
}
}
interface IRouter {
function swap(address tokenIn, address tokenOut, uint256 amountIn, uint256 minOut, address to) external;
}
6. Continuous Performance Monitoring
// Performance monitoring configuration
interface PerformanceMonitor {
metrics: {
// Latency metrics
'api.latency.p50': Gauge;
'api.latency.p95': Gauge;
'api.latency.p99': Gauge;
// Throughput metrics
'tx.throughput.current': Counter;
'tx.throughput.peak': Gauge;
// Error metrics
'error.rate': Gauge;
'error.count': Counter;
// Resource metrics
'resource.cpu.usage': Gauge;
'resource.memory.usage': Gauge;
'resource.gas.average': Gauge;
};
alerts: AlertRule[];
dashboards: Dashboard[];
}
interface AlertRule {
name: string;
condition: string;
threshold: number;
duration: string;
severity: 'warning' | 'critical';
action: 'page' | 'slack' | 'email';
}
const performanceAlerts: AlertRule[] = [
{
name: 'high_latency',
condition: 'api.latency.p99 > threshold',
threshold: 500,
duration: '5m',
severity: 'warning',
action: 'slack',
},
{
name: 'error_spike',
condition: 'error.rate > threshold',
threshold: 0.01,
duration: '1m',
severity: 'critical',
action: 'page',
},
{
name: 'throughput_drop',
condition: 'tx.throughput.current < threshold',
threshold: 1000,
duration: '5m',
severity: 'warning',
action: 'slack',
},
];
7. Capacity Planning
| Daily Volume | Required TPS | Infra Tier | Estimated Cost |
|---|---|---|---|
| $100M | 500 | Standard | $10K/month |
| $1B | 5,000 | Enhanced | $50K/month |
| $10B | 50,000 | Enterprise | $200K/month |
| $100B | 500,000 | Planet-scale | $1M/month |
8. Performance SLAs
| Metric | SLA | Measurement |
|---|---|---|
| Uptime | 99.9% | Monthly |
| API Latency (p99) | < 500ms | Rolling 5min |
| Transaction Success | 99.5% | Daily |
| Price Accuracy | 99.99% | Per update |
| Recovery Time | < 5min | Per incident |
Test Cases
- Sustained 10K TPS for 1 hour with < 0.1% error rate
- Traffic spike to 50K TPS with graceful degradation
- 24-hour endurance test with stable memory usage
- Failover completes in < 5 seconds
- Gas costs within 110% of targets
Rationale
Performance benchmarks establish verifiable baselines for protocol reliability. Target metrics are derived from competitive analysis and user experience requirements. Continuous benchmarking prevents performance regression and guides optimization efforts.
Backwards Compatibility
Benchmarking infrastructure is observational and doesn't modify protocol behavior. Performance improvements may change gas costs, which are documented with each upgrade.
Security Considerations
- DoS protection - Rate limiting under load
- Resource isolation - Prevent cascade failures
- Graceful degradation - Prioritize critical operations
- Circuit breakers - Auto-protection at capacity
Copyright
Copyright and related rights waived via CC0.