refactor: move all remaining files to orig/ directory
Completed clean root directory structure: - Root now contains only: .git, .env, docs/, orig/ - Moved all remaining files and directories to orig/: - Config files (.claude, .dockerignore, .drone.yml, etc.) - All .env variants (except active .env) - Git config (.gitconfig, .github, .gitignore, etc.) - Tool configs (.golangci.yml, .revive.toml, etc.) - Documentation (*.md files, @prompts) - Build files (Dockerfiles, Makefile, go.mod, go.sum) - Docker compose files - All source directories (scripts, tests, tools, etc.) - Runtime directories (logs, monitoring, reports) - Dependency files (node_modules, lib, cache) - Special files (--delete) - Removed empty runtime directories (bin/, data/) V2 structure is now clean: - docs/planning/ - V2 planning documents - orig/ - Complete V1 codebase preserved - .env - Active environment config (not in git) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
818
orig/test/stress/benchmarks.go
Normal file
818
orig/test/stress/benchmarks.go
Normal file
@@ -0,0 +1,818 @@
|
||||
//go:build stress
|
||||
// +build stress
|
||||
|
||||
package stress_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/holiman/uint256"
|
||||
|
||||
"github.com/fraktal/mev-beta/internal/logger"
|
||||
"github.com/fraktal/mev-beta/pkg/arbitrum"
|
||||
"github.com/fraktal/mev-beta/pkg/events"
|
||||
"github.com/fraktal/mev-beta/pkg/pools"
|
||||
"github.com/fraktal/mev-beta/pkg/profitcalc"
|
||||
"github.com/fraktal/mev-beta/pkg/scanner/market"
|
||||
"github.com/fraktal/mev-beta/pkg/trading"
|
||||
)
|
||||
|
||||
// BenchmarkStressTestSuite runs benchmark tests for the stress test suite
|
||||
func BenchmarkStressTestSuite(b *testing.B) {
|
||||
// Create test logger
|
||||
log := logger.New("warn", "text", "") // Use warn level to minimize logging overhead
|
||||
|
||||
// Create test components
|
||||
protocolRegistry := arbitrum.NewArbitrumProtocolRegistry(log)
|
||||
poolCache := pools.NewPoolCache(10000, time.Hour)
|
||||
marketDiscovery := market.NewMarketDiscovery(nil, log, "")
|
||||
strategyEngine := arbitrum.NewMEVStrategyEngine(log, protocolRegistry)
|
||||
profitCalculator := profitcalc.NewProfitCalculatorWithClient(log, nil)
|
||||
mevAnalyzer := arbitrum.NewMEVAnalyzer(log)
|
||||
slippageProtector := trading.NewSlippageProtection(nil, log)
|
||||
capitalOptimizer := arbitrum.NewCapitalOptimizer(log)
|
||||
profitTracker := arbitrum.NewProfitabilityTracker(log)
|
||||
|
||||
// Create stress test suite
|
||||
suite := NewStressTestSuite(
|
||||
log,
|
||||
protocolRegistry,
|
||||
poolCache,
|
||||
marketDiscovery,
|
||||
strategyEngine,
|
||||
profitCalculator,
|
||||
mevAnalyzer,
|
||||
slippageProtector,
|
||||
capitalOptimizer,
|
||||
profitTracker,
|
||||
)
|
||||
|
||||
// Run benchmark tests
|
||||
b.Run("MarketScannerStressTest", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
result := suite.RunMarketScannerStressTest()
|
||||
if !result.Passed {
|
||||
b.Fatalf("Market scanner stress test failed: %v", result.Errors)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("SwapAnalyzerStressTest", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
result := suite.RunSwapAnalyzerStressTest()
|
||||
if !result.Passed {
|
||||
b.Fatalf("Swap analyzer stress test failed: %v", result.Errors)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("PoolDiscoveryStressTest", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
result := suite.RunPoolDiscoveryStressTest()
|
||||
if !result.Passed {
|
||||
b.Fatalf("Pool discovery stress test failed: %v", result.Errors)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("ArbitrageEngineStressTest", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
result := suite.RunArbitrageEngineStressTest()
|
||||
if !result.Passed {
|
||||
b.Fatalf("Arbitrage engine stress test failed: %v", result.Errors)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("EventProcessingStressTest", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
result := suite.RunEventProcessingStressTest()
|
||||
if !result.Passed {
|
||||
b.Fatalf("Event processing stress test failed: %v", result.Errors)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("ProfitCalculationStressTest", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
result := suite.RunProfitCalculationStressTest()
|
||||
if !result.Passed {
|
||||
b.Fatalf("Profit calculation stress test failed: %v", result.Errors)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("ConcurrencyStressTest", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
result := suite.RunConcurrencyStressTest()
|
||||
if !result.Passed {
|
||||
b.Fatalf("Concurrency stress test failed: %v", result.Errors)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("MemoryStressTest", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
result := suite.RunMemoryStressTest()
|
||||
if !result.Passed {
|
||||
b.Fatalf("Memory stress test failed: %v", result.Errors)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("PerformanceRegressionTest", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
result := suite.RunPerformanceRegressionTest()
|
||||
if !result.Passed {
|
||||
b.Fatalf("Performance regression test failed: %v", result.Errors)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// BenchmarkConcurrentMarketScanning benchmarks concurrent market scanning performance
|
||||
func BenchmarkConcurrentMarketScanning(b *testing.B) {
|
||||
// Create test logger
|
||||
log := logger.New("warn", "text", "") // Use warn level to minimize logging overhead
|
||||
|
||||
// Create test components
|
||||
protocolRegistry := arbitrum.NewArbitrumProtocolRegistry(log)
|
||||
poolCache := pools.NewPoolCache(10000, time.Hour)
|
||||
marketDiscovery := market.NewMarketDiscovery(nil, log, "")
|
||||
strategyEngine := arbitrum.NewMEVStrategyEngine(log, protocolRegistry)
|
||||
profitCalculator := profitcalc.NewProfitCalculatorWithClient(log, nil)
|
||||
mevAnalyzer := arbitrum.NewMEVAnalyzer(log)
|
||||
slippageProtector := trading.NewSlippageProtection(nil, log)
|
||||
capitalOptimizer := arbitrum.NewCapitalOptimizer(log)
|
||||
profitTracker := arbitrum.NewProfitabilityTracker(log)
|
||||
|
||||
// Create stress test suite
|
||||
suite := NewStressTestSuite(
|
||||
log,
|
||||
protocolRegistry,
|
||||
poolCache,
|
||||
marketDiscovery,
|
||||
strategyEngine,
|
||||
profitCalculator,
|
||||
mevAnalyzer,
|
||||
slippageProtector,
|
||||
capitalOptimizer,
|
||||
profitTracker,
|
||||
)
|
||||
|
||||
// Generate test data
|
||||
testPools := suite.generateTestPools(1000)
|
||||
testEvents := suite.generateTestEvents(10000)
|
||||
|
||||
b.ResetTimer()
|
||||
b.Run("ConcurrentPoolScanning", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
var wg sync.WaitGroup
|
||||
errorCount := int64(0)
|
||||
|
||||
// Process pools concurrently
|
||||
for _, pool := range testPools {
|
||||
wg.Add(1)
|
||||
go func(p *market.CachedData) {
|
||||
defer wg.Done()
|
||||
|
||||
// Simulate pool scanning
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// Mock pool scanning operation
|
||||
err := suite.mockPoolScan(ctx, p)
|
||||
if err != nil {
|
||||
atomic.AddInt64(&errorCount, 1)
|
||||
}
|
||||
}(pool)
|
||||
}
|
||||
|
||||
// Wait for all operations to complete
|
||||
wg.Wait()
|
||||
|
||||
if errorCount > 0 {
|
||||
b.Fatalf("Concurrent pool scanning failed with %d errors", errorCount)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("ConcurrentEventProcessing", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
var wg sync.WaitGroup
|
||||
errorCount := int64(0)
|
||||
|
||||
// Process events concurrently
|
||||
for _, event := range testEvents {
|
||||
wg.Add(1)
|
||||
go func(e events.Event) {
|
||||
defer wg.Done()
|
||||
|
||||
// Simulate event processing
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// Mock event processing operation
|
||||
err := suite.mockEventProcessing(ctx, e)
|
||||
if err != nil {
|
||||
atomic.AddInt64(&errorCount, 1)
|
||||
}
|
||||
}(event)
|
||||
}
|
||||
|
||||
// Wait for all operations to complete
|
||||
wg.Wait()
|
||||
|
||||
if errorCount > 0 {
|
||||
b.Fatalf("Concurrent event processing failed with %d errors", errorCount)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// BenchmarkMemoryAllocation benchmarks memory allocation performance
|
||||
func BenchmarkMemoryAllocation(b *testing.B) {
|
||||
// Create test logger
|
||||
log := logger.New("warn", "text", "") // Use warn level to minimize logging overhead
|
||||
|
||||
// Create test components
|
||||
protocolRegistry := arbitrum.NewArbitrumProtocolRegistry(log)
|
||||
poolCache := pools.NewPoolCache(10000, time.Hour)
|
||||
marketDiscovery := market.NewMarketDiscovery(nil, log, "")
|
||||
strategyEngine := arbitrum.NewMEVStrategyEngine(log, protocolRegistry)
|
||||
profitCalculator := profitcalc.NewProfitCalculatorWithClient(log, nil)
|
||||
mevAnalyzer := arbitrum.NewMEVAnalyzer(log)
|
||||
slippageProtector := trading.NewSlippageProtection(nil, log)
|
||||
capitalOptimizer := arbitrum.NewCapitalOptimizer(log)
|
||||
profitTracker := arbitrum.NewProfitabilityTracker(log)
|
||||
|
||||
// Create stress test suite
|
||||
suite := NewStressTestSuite(
|
||||
log,
|
||||
protocolRegistry,
|
||||
poolCache,
|
||||
marketDiscovery,
|
||||
strategyEngine,
|
||||
profitCalculator,
|
||||
mevAnalyzer,
|
||||
slippageProtector,
|
||||
capitalOptimizer,
|
||||
profitTracker,
|
||||
)
|
||||
|
||||
b.ResetTimer()
|
||||
b.Run("LargeDataStructures", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
// Generate large test data sets
|
||||
dataSets := suite.generateLargeTestDataSets(10000)
|
||||
|
||||
// Process large data sets
|
||||
var wg sync.WaitGroup
|
||||
errorCount := int64(0)
|
||||
|
||||
for _, dataSet := range dataSets {
|
||||
wg.Add(1)
|
||||
go func(ds []*market.CachedData) {
|
||||
defer wg.Done()
|
||||
|
||||
// Simulate memory-intensive processing
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// Mock memory-intensive operation
|
||||
err := suite.mockMemoryIntensiveProcessing(ctx, ds)
|
||||
if err != nil {
|
||||
atomic.AddInt64(&errorCount, 1)
|
||||
}
|
||||
}(dataSet)
|
||||
}
|
||||
|
||||
// Wait for all operations to complete
|
||||
wg.Wait()
|
||||
|
||||
if errorCount > 0 {
|
||||
b.Fatalf("Memory-intensive processing failed with %d errors", errorCount)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// BenchmarkCPUUtilization benchmarks CPU utilization performance
|
||||
func BenchmarkCPUUtilization(b *testing.B) {
|
||||
// Create test logger
|
||||
log := logger.New("warn", "text", "") // Use warn level to minimize logging overhead
|
||||
|
||||
// Create test components
|
||||
protocolRegistry := arbitrum.NewArbitrumProtocolRegistry(log)
|
||||
poolCache := pools.NewPoolCache(10000, time.Hour)
|
||||
marketDiscovery := market.NewMarketDiscovery(nil, log, "")
|
||||
strategyEngine := arbitrum.NewMEVStrategyEngine(log, protocolRegistry)
|
||||
profitCalculator := profitcalc.NewProfitCalculatorWithClient(log, nil)
|
||||
mevAnalyzer := arbitrum.NewMEVAnalyzer(log)
|
||||
slippageProtector := trading.NewSlippageProtection(nil, log)
|
||||
capitalOptimizer := arbitrum.NewCapitalOptimizer(log)
|
||||
profitTracker := arbitrum.NewProfitabilityTracker(log)
|
||||
|
||||
// Create stress test suite
|
||||
suite := NewStressTestSuite(
|
||||
log,
|
||||
protocolRegistry,
|
||||
poolCache,
|
||||
marketDiscovery,
|
||||
strategyEngine,
|
||||
profitCalculator,
|
||||
mevAnalyzer,
|
||||
slippageProtector,
|
||||
capitalOptimizer,
|
||||
profitTracker,
|
||||
)
|
||||
|
||||
b.ResetTimer()
|
||||
b.Run("CPUIntensiveCalculations", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
// Generate test data
|
||||
testProfits := suite.generateTestProfits(1000)
|
||||
|
||||
// Process profits concurrently
|
||||
var wg sync.WaitGroup
|
||||
errorCount := int64(0)
|
||||
|
||||
for _, profit := range testProfits {
|
||||
wg.Add(1)
|
||||
go func(p *arbitrum.ArbitrageOpportunityDetailed) {
|
||||
defer wg.Done()
|
||||
|
||||
// Simulate CPU-intensive calculations
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// Mock profit calculation operation
|
||||
err := suite.mockProfitCalculation(ctx, p)
|
||||
if err != nil {
|
||||
atomic.AddInt64(&errorCount, 1)
|
||||
}
|
||||
}(profit)
|
||||
}
|
||||
|
||||
// Wait for all operations to complete
|
||||
wg.Wait()
|
||||
|
||||
if errorCount > 0 {
|
||||
b.Fatalf("CPU-intensive calculations failed with %d errors", errorCount)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// BenchmarkNetworkLatency benchmarks network latency handling
|
||||
func BenchmarkNetworkLatency(b *testing.B) {
|
||||
// Create test logger
|
||||
log := logger.New("warn", "text", "") // Use warn level to minimize logging overhead
|
||||
|
||||
// Create test components
|
||||
protocolRegistry := arbitrum.NewArbitrumProtocolRegistry(log)
|
||||
poolCache := pools.NewPoolCache(10000, time.Hour)
|
||||
marketDiscovery := market.NewMarketDiscovery(nil, log, "")
|
||||
strategyEngine := arbitrum.NewMEVStrategyEngine(log, protocolRegistry)
|
||||
profitCalculator := profitcalc.NewProfitCalculatorWithClient(log, nil)
|
||||
mevAnalyzer := arbitrum.NewMEVAnalyzer(log)
|
||||
slippageProtector := trading.NewSlippageProtection(nil, log)
|
||||
capitalOptimizer := arbitrum.NewCapitalOptimizer(log)
|
||||
profitTracker := arbitrum.NewProfitabilityTracker(log)
|
||||
|
||||
// Create stress test suite
|
||||
suite := NewStressTestSuite(
|
||||
log,
|
||||
protocolRegistry,
|
||||
poolCache,
|
||||
marketDiscovery,
|
||||
strategyEngine,
|
||||
profitCalculator,
|
||||
mevAnalyzer,
|
||||
slippageProtector,
|
||||
capitalOptimizer,
|
||||
profitTracker,
|
||||
)
|
||||
|
||||
b.ResetTimer()
|
||||
b.Run("NetworkRequestHandling", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
// Generate test data
|
||||
testPools := suite.generateTestPools(100)
|
||||
|
||||
// Process pools with simulated network delays
|
||||
var wg sync.WaitGroup
|
||||
errorCount := int64(0)
|
||||
|
||||
for _, pool := range testPools {
|
||||
wg.Add(1)
|
||||
go func(p *market.CachedData) {
|
||||
defer wg.Done()
|
||||
|
||||
// Simulate network delay
|
||||
time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
|
||||
|
||||
// Simulate pool scanning with network request
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// Mock pool scanning operation
|
||||
err := suite.mockPoolScan(ctx, p)
|
||||
if err != nil {
|
||||
atomic.AddInt64(&errorCount, 1)
|
||||
}
|
||||
}(pool)
|
||||
}
|
||||
|
||||
// Wait for all operations to complete
|
||||
wg.Wait()
|
||||
|
||||
if errorCount > 0 {
|
||||
b.Fatalf("Network request handling failed with %d errors", errorCount)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// BenchmarkErrorHandling benchmarks error handling performance
|
||||
func BenchmarkErrorHandling(b *testing.B) {
|
||||
// Create test logger
|
||||
log := logger.New("warn", "text", "") // Use warn level to minimize logging overhead
|
||||
|
||||
// Create test components
|
||||
protocolRegistry := arbitrum.NewArbitrumProtocolRegistry(log)
|
||||
poolCache := pools.NewPoolCache(10000, time.Hour)
|
||||
marketDiscovery := market.NewMarketDiscovery(nil, log, "")
|
||||
strategyEngine := arbitrum.NewMEVStrategyEngine(log, protocolRegistry)
|
||||
profitCalculator := profitcalc.NewProfitCalculatorWithClient(log, nil)
|
||||
mevAnalyzer := arbitrum.NewMEVAnalyzer(log)
|
||||
slippageProtector := trading.NewSlippageProtection(nil, log)
|
||||
capitalOptimizer := arbitrum.NewCapitalOptimizer(log)
|
||||
profitTracker := arbitrum.NewProfitabilityTracker(log)
|
||||
|
||||
// Create stress test suite
|
||||
suite := NewStressTestSuite(
|
||||
log,
|
||||
protocolRegistry,
|
||||
poolCache,
|
||||
marketDiscovery,
|
||||
strategyEngine,
|
||||
profitCalculator,
|
||||
mevAnalyzer,
|
||||
slippageProtector,
|
||||
capitalOptimizer,
|
||||
profitTracker,
|
||||
)
|
||||
|
||||
b.ResetTimer()
|
||||
b.Run("ErrorHandlingPerformance", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
// Generate test data with errors
|
||||
testEvents := suite.generateTestEventsWithErrorRate(1000, 0.05) // 5% error rate
|
||||
|
||||
// Process events with error handling
|
||||
var wg sync.WaitGroup
|
||||
errorCount := int64(0)
|
||||
successCount := int64(0)
|
||||
|
||||
for _, event := range testEvents {
|
||||
wg.Add(1)
|
||||
go func(e events.Event) {
|
||||
defer wg.Done()
|
||||
|
||||
// Simulate event processing
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// Mock event processing operation
|
||||
err := suite.mockEventProcessing(ctx, e)
|
||||
if err != nil {
|
||||
atomic.AddInt64(&errorCount, 1)
|
||||
suite.recordError(fmt.Sprintf("EventProcessingError: %v", err))
|
||||
} else {
|
||||
atomic.AddInt64(&successCount, 1)
|
||||
}
|
||||
}(event)
|
||||
}
|
||||
|
||||
// Wait for all operations to complete
|
||||
wg.Wait()
|
||||
|
||||
// Validate error handling worked correctly
|
||||
if errorCount+successCount != int64(len(testEvents)) {
|
||||
b.Fatalf("Error handling count mismatch: %d errors + %d successes != %d total", errorCount, successCount, len(testEvents))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// generateTestEventsWithErrorRate generates test events with a specific error rate
|
||||
func (suite *StressTestSuite) generateTestEventsWithErrorRate(count int, errorRate float64) []events.Event {
|
||||
events := suite.generateTestEvents(count)
|
||||
|
||||
// Mark some events to cause errors based on error rate
|
||||
errorEvents := int(float64(count) * errorRate)
|
||||
for i := 0; i < errorEvents && i < count; i++ {
|
||||
// Mark event to cause error
|
||||
events[i].Type = events.Unknown // Invalid event type to cause processing errors
|
||||
}
|
||||
|
||||
return events
|
||||
}
|
||||
|
||||
// generateTestPools generates test pools for benchmarking
|
||||
func (suite *StressTestSuite) generateTestPools(count int) []*market.CachedData {
|
||||
pools := make([]*market.CachedData, count)
|
||||
|
||||
// Known token addresses for testing
|
||||
wethAddr := common.HexToAddress("0x82af49447d8a07e3bd95bd0d56f35241523fbab1")
|
||||
usdcAddr := common.HexToAddress("0xaf88d065e77c8cc2239327c5edb3a432268e5831")
|
||||
usdtAddr := common.HexToAddress("0xff970a61a04b1ca14834a43f5de4533ebddb5cc8")
|
||||
wbtcAddr := common.HexToAddress("0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f")
|
||||
|
||||
tokens := []common.Address{wethAddr, usdcAddr, usdtAddr, wbtcAddr}
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
// Select random tokens for the pool
|
||||
token0 := tokens[rand.Intn(len(tokens))]
|
||||
token1 := tokens[rand.Intn(len(tokens))]
|
||||
for token0 == token1 {
|
||||
token1 = tokens[rand.Intn(len(tokens))]
|
||||
}
|
||||
|
||||
// Create deterministic pool address based on index
|
||||
poolAddr := common.BigToAddress(big.NewInt(int64(i + 1000000)))
|
||||
|
||||
// Generate deterministic liquidity and price values
|
||||
liquidity := uint256.NewInt(uint64(1000000 + i*1000)) // Increasing liquidity
|
||||
sqrtPrice := uint256.NewInt(uint64(1000000000000000000 + i*100000000000000)) // Increasing price
|
||||
|
||||
pools[i] = &market.CachedData{
|
||||
Address: poolAddr,
|
||||
Token0: token0,
|
||||
Token1: token1,
|
||||
Fee: int64(3000 + (i%4)*500), // Varying fees (0.05%, 0.3%, 0.5%, 1%)
|
||||
Liquidity: liquidity,
|
||||
SqrtPriceX96: sqrtPrice,
|
||||
Tick: int(74959 + i), // Varying ticks
|
||||
TickSpacing: 60,
|
||||
Protocol: fmt.Sprintf("uniswap_v%d", 2+(i%2)), // Alternating V2/V3
|
||||
LastUpdated: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
return pools
|
||||
}
|
||||
|
||||
// generateTestEvents generates test events for benchmarking
|
||||
func (suite *StressTestSuite) generateTestEvents(count int) []events.Event {
|
||||
events := make([]events.Event, count)
|
||||
|
||||
// Known token addresses for testing
|
||||
wethAddr := common.HexToAddress("0x82af49447d8a07e3bd95bd0d56f35241523fbab1")
|
||||
usdcAddr := common.HexToAddress("0xaf88d065e77c8cc2239327c5edb3a432268e5831")
|
||||
usdtAddr := common.HexToAddress("0xff970a61a04b1ca14834a43f5de4533ebddb5cc8")
|
||||
wbtcAddr := common.HexToAddress("0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f")
|
||||
|
||||
tokens := []common.Address{wethAddr, usdcAddr, usdtAddr, wbtcAddr}
|
||||
protocols := []string{"uniswap_v2", "uniswap_v3", "sushiswap", "camelot_v2", "camelot_v3", "balancer_v2", "curve", "algebra"}
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
// Select random tokens for the event
|
||||
token0 := tokens[rand.Intn(len(tokens))]
|
||||
token1 := tokens[rand.Intn(len(tokens))]
|
||||
for token0 == token1 {
|
||||
token1 = tokens[rand.Intn(len(tokens))]
|
||||
}
|
||||
|
||||
// Select random protocol
|
||||
protocol := protocols[rand.Intn(len(protocols))]
|
||||
|
||||
// Create deterministic pool address based on index
|
||||
poolAddr := common.BigToAddress(big.NewInt(int64(i + 2000000)))
|
||||
|
||||
// Generate deterministic amounts
|
||||
amount0 := big.NewInt(int64(100000000000000000 + int64(i)*10000000000000)) // Varying amounts
|
||||
amount1 := big.NewInt(int64(200000000000000000 + int64(i)*20000000000000)) // Varying amounts
|
||||
|
||||
// Generate deterministic liquidity and price values
|
||||
liquidity := uint256.NewInt(uint64(500000 + i*500)) // Increasing liquidity
|
||||
sqrtPrice := uint256.NewInt(uint64(500000000000000000 + i*50000000000000)) // Increasing price
|
||||
|
||||
events[i] = events.Event{
|
||||
Timestamp: time.Now(),
|
||||
BlockNumber: uint64(10000000 + i),
|
||||
TransactionHash: common.BigToHash(big.NewInt(int64(i + 3000000))),
|
||||
LogIndex: uint(i % 100),
|
||||
Type: events.Swap, // Default to swap events
|
||||
Protocol: protocol,
|
||||
PoolAddress: poolAddr,
|
||||
Token0: token0,
|
||||
Token1: token1,
|
||||
Amount0: amount0,
|
||||
Amount1: amount1,
|
||||
Liquidity: liquidity,
|
||||
SqrtPriceX96: sqrtPrice,
|
||||
Tick: int32(74959 + i%1000), // Varying ticks
|
||||
}
|
||||
}
|
||||
|
||||
return events
|
||||
}
|
||||
|
||||
// generateTestProfits generates test profits for benchmarking
|
||||
func (suite *StressTestSuite) generateTestProfits(count int) []*arbitrum.ArbitrageOpportunityDetailed {
|
||||
profits := make([]*arbitrum.ArbitrageOpportunityDetailed, count)
|
||||
|
||||
// Known token addresses for testing
|
||||
wethAddr := common.HexToAddress("0x82af49447d8a07e3bd95bd0d56f35241523fbab1")
|
||||
usdcAddr := common.HexToAddress("0xaf88d065e77c8cc2239327c5edb3a432268e5831")
|
||||
usdtAddr := common.HexToAddress("0xff970a61a04b1ca14834a43f5de4533ebddb5cc8")
|
||||
wbtcAddr := common.HexToAddress("0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f")
|
||||
|
||||
tokens := []common.Address{wethAddr, usdcAddr, usdtAddr, wbtcAddr}
|
||||
exchanges := []string{"uniswap_v2", "uniswap_v3", "sushiswap", "camelot_v2", "camelot_v3", "balancer_v2", "curve", "algebra"}
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
// Select random tokens for the arbitrage
|
||||
tokenIn := tokens[rand.Intn(len(tokens))]
|
||||
tokenOut := tokens[rand.Intn(len(tokens))]
|
||||
for tokenIn == tokenOut {
|
||||
tokenOut = tokens[rand.Intn(len(tokens))]
|
||||
}
|
||||
|
||||
// Select random exchanges
|
||||
exchangeA := exchanges[rand.Intn(len(exchanges))]
|
||||
exchangeB := exchanges[rand.Intn(len(exchanges))]
|
||||
for exchangeA == exchangeB {
|
||||
exchangeB = exchanges[rand.Intn(len(exchanges))]
|
||||
}
|
||||
|
||||
// Create deterministic pool addresses based on index
|
||||
poolA := common.BigToAddress(big.NewInt(int64(i + 4000000)))
|
||||
poolB := common.BigToAddress(big.NewInt(int64(i + 5000000)))
|
||||
|
||||
// Generate deterministic amounts
|
||||
amountIn := big.NewInt(int64(100000000000000000 + int64(i)*10000000000000)) // Varying amounts
|
||||
expectedAmountOut := big.NewInt(int64(105000000000000000 + int64(i)*10500000000000)) // 5% profit
|
||||
actualAmountOut := big.NewInt(int64(104000000000000000 + int64(i)*10400000000000)) // 4% profit
|
||||
profit := big.NewInt(int64(4000000000000000 + int64(i)*400000000000)) // Varying profits
|
||||
gasCost := big.NewInt(int64(1000000000000000 + int64(i)*100000000000)) // Varying gas costs
|
||||
netProfit := new(big.Int).Sub(profit, gasCost)
|
||||
|
||||
profits[i] = &arbitrum.ArbitrageOpportunityDetailed{
|
||||
ID: fmt.Sprintf("arb_%d_%d", time.Now().Unix(), i+1000000),
|
||||
Type: "arbitrage",
|
||||
TokenIn: tokenIn,
|
||||
TokenOut: tokenOut,
|
||||
AmountIn: amountIn,
|
||||
ExpectedAmountOut: expectedAmountOut,
|
||||
ActualAmountOut: actualAmountOut,
|
||||
Profit: profit,
|
||||
ProfitUSD: 50.0 + float64(i%1000)*0.05, // Varying USD profits
|
||||
ProfitMargin: 0.04 + float64(i%100)*0.0001, // Varying margins (4-5%)
|
||||
GasCost: gasCost,
|
||||
NetProfit: netProfit,
|
||||
ExchangeA: exchangeA,
|
||||
ExchangeB: exchangeB,
|
||||
PoolA: poolA,
|
||||
PoolB: poolB,
|
||||
PriceImpactA: 0.005 + float64(i%1000)*0.000005, // Varying price impacts
|
||||
PriceImpactB: 0.003 + float64(i%1000)*0.000003, // Varying price impacts
|
||||
CapitalRequired: 100.0 + float64(i%10000)*0.01, // Varying capital requirements
|
||||
GasCostUSD: 5.0 + float64(i%100)*0.05, // Varying gas costs in USD
|
||||
Confidence: 0.8 + float64(i%20)*0.01, // Varying confidence (80-100%)
|
||||
RiskScore: 0.2 + float64(i%50)*0.01, // Varying risk scores (20-70%)
|
||||
ExecutionTime: time.Duration(15+i%10) * time.Second, // Varying execution times
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
return profits
|
||||
}
|
||||
|
||||
// generateLargeTestDataSets generates large test data sets for memory benchmarking
|
||||
func (suite *StressTestSuite) generateLargeTestDataSets(count int) [][]*market.CachedData {
|
||||
// Create batches of test data
|
||||
batchSize := 1000
|
||||
batchCount := count / batchSize
|
||||
if count%batchSize > 0 {
|
||||
batchCount++
|
||||
}
|
||||
|
||||
dataSets := make([][]*market.CachedData, batchCount)
|
||||
|
||||
for i := 0; i < batchCount; i++ {
|
||||
dataSets[i] = suite.generateTestPools(batchSize)
|
||||
}
|
||||
|
||||
return dataSets
|
||||
}
|
||||
|
||||
// mockPoolScan simulates pool scanning for benchmarking
|
||||
func (suite *StressTestSuite) mockPoolScan(ctx context.Context, pool *market.CachedData) error {
|
||||
atomic.AddUint64(&suite.metrics.totalPoolsScanned, 1)
|
||||
atomic.AddUint64(&suite.metrics.totalTestsRun, 1)
|
||||
|
||||
// Simulate work
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-time.After(time.Duration(rand.Intn(10)) * time.Millisecond):
|
||||
// Simulate occasional errors
|
||||
if rand.Intn(1000) < 5 { // 0.5% error rate
|
||||
atomic.AddUint64(&suite.metrics.testsFailed, 1)
|
||||
return fmt.Errorf("simulated pool scan error")
|
||||
}
|
||||
|
||||
atomic.AddUint64(&suite.metrics.testsPassed, 1)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// mockEventProcessing simulates event processing for benchmarking
|
||||
func (suite *StressTestSuite) mockEventProcessing(ctx context.Context, event events.Event) error {
|
||||
atomic.AddUint64(&suite.metrics.totalTransactions, 1)
|
||||
atomic.AddUint64(&suite.metrics.totalTestsRun, 1)
|
||||
|
||||
// Simulate work
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-time.After(time.Duration(rand.Intn(5)) * time.Millisecond):
|
||||
// Simulate occasional errors
|
||||
if rand.Intn(1000) < 3 { // 0.3% error rate
|
||||
atomic.AddUint64(&suite.metrics.testsFailed, 1)
|
||||
return fmt.Errorf("simulated event processing error")
|
||||
}
|
||||
|
||||
atomic.AddUint64(&suite.metrics.testsPassed, 1)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// mockMemoryIntensiveProcessing simulates memory-intensive processing for benchmarking
|
||||
func (suite *StressTestSuite) mockMemoryIntensiveProcessing(ctx context.Context, dataSet []*market.CachedData) error {
|
||||
atomic.AddUint64(&suite.metrics.totalTestsRun, 1)
|
||||
|
||||
// Simulate memory-intensive work
|
||||
// Create temporary data structures to consume memory
|
||||
tempData := make([]*market.CachedData, len(dataSet))
|
||||
copy(tempData, dataSet)
|
||||
|
||||
// Simulate work
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-time.After(time.Duration(rand.Intn(20)) * time.Millisecond):
|
||||
// Clear temporary data
|
||||
tempData = nil
|
||||
|
||||
// Simulate occasional errors
|
||||
if rand.Intn(1000) < 8 { // 0.8% error rate
|
||||
atomic.AddUint64(&suite.metrics.testsFailed, 1)
|
||||
return fmt.Errorf("simulated memory-intensive processing error")
|
||||
}
|
||||
|
||||
atomic.AddUint64(&suite.metrics.testsPassed, 1)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// mockProfitCalculation simulates profit calculation for benchmarking
|
||||
func (suite *StressTestSuite) mockProfitCalculation(ctx context.Context, profit *arbitrum.ArbitrageOpportunityDetailed) error {
|
||||
atomic.AddUint64(&suite.metrics.totalArbitrageOps, 1)
|
||||
atomic.AddUint64(&suite.metrics.totalTestsRun, 1)
|
||||
|
||||
// Simulate work
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-time.After(time.Duration(rand.Intn(15)) * time.Millisecond):
|
||||
// Simulate occasional errors
|
||||
if rand.Intn(1000) < 6 { // 0.6% error rate
|
||||
atomic.AddUint64(&suite.metrics.testsFailed, 1)
|
||||
return fmt.Errorf("simulated profit calculation error")
|
||||
}
|
||||
|
||||
atomic.AddUint64(&suite.metrics.testsPassed, 1)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user