LPsLux Proposals
DEX & Trading
LP-9020

Performance Benchmarks & Stress Testing

Draft

Performance requirements, benchmarks, and stress testing standards for production DeFi

Category
Core
Created
2025-01-15

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

ComponentMetricMinimumTargetExceptional
DEX Engine
Order PlacementLatency< 50ms< 20ms< 5ms
Order MatchingThroughput10K/s100K/s1M/s
Price UpdatesLatency< 100ms< 50ms< 10ms
Oracle
Price FetchLatency< 200ms< 100ms< 50ms
AggregationLatency< 500ms< 200ms< 100ms
Update FrequencyRate1/min1/sec100/sec
Bridge
Message DeliveryLatency< 30s< 10s< 3s
FinalityTime< 60s< 30s< 10s
ThroughputTPS1001,00010,000
Smart Contracts
Swap ExecutionGas250K150K100K
Complex RouteGas500K300K200K
Batch OperationsGas/op50K30K20K

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:

StageMetricDay-1 targetSource
D-Chain matchp50 latency / shard< 1 msmeasured; see benchmark suite
D-Chain matchp99 latency / shard< 10 msmeasured; see benchmark suite
C-Chain verifyBLS root verificationonce per batch (amortized over all receipts in the batch)measured; see benchmark suite
C-Chain settleparallel settlementBlock-STM, fine-grained keys, no global hot slots (LP-1024)measured; see benchmark suite
End-to-endp50 (order → settled)within a few fast blocksmeasured; 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 VolumeRequired TPSInfra TierEstimated Cost
$100M500Standard$10K/month
$1B5,000Enhanced$50K/month
$10B50,000Enterprise$200K/month
$100B500,000Planet-scale$1M/month

8. Performance SLAs

MetricSLAMeasurement
Uptime99.9%Monthly
API Latency (p99)< 500msRolling 5min
Transaction Success99.5%Daily
Price Accuracy99.99%Per update
Recovery Time< 5minPer incident

Test Cases

  1. Sustained 10K TPS for 1 hour with < 0.1% error rate
  2. Traffic spike to 50K TPS with graceful degradation
  3. 24-hour endurance test with stable memory usage
  4. Failover completes in < 5 seconds
  5. 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

  1. DoS protection - Rate limiting under load
  2. Resource isolation - Prevent cascade failures
  3. Graceful degradation - Prioritize critical operations
  4. Circuit breakers - Auto-protection at capacity

Copyright and related rights waived via CC0.