test(08-02): add performance tests with large datasets

Added 4 performance tests with 1K, 5K, 10K games to validate DAG
algorithm scalability. Tests currently failing (RED phase).

Tests:
- 1K games: <2s expected
- 5K games: <10s expected
- 10K games: <30s expected
- 10K games: memory stability

Helper generateLargeDataset() creates realistic test data with
distributed stadiums and games across time spans.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-01-10 11:58:51 -06:00
parent 6e00663fec
commit 13be6ffca5

View File

@@ -534,4 +534,113 @@ struct GameDAGRouterTests {
#expect(routeWithBoth != nil, "4 hours available (with 1hr arrival buffer) should be feasible")
}
// MARK: - Performance Tests
/// Generates a large dataset of games and stadiums for performance testing.
/// Games are distributed across stadiums and days to simulate realistic data.
private func generateLargeDataset(
gameCount: Int,
stadiumCount: Int,
daysSpan: Int
) -> (games: [Game], stadiums: [UUID: Stadium]) {
// Create stadiums distributed across the US (roughly)
var stadiums: [UUID: Stadium] = [:]
let baseDate = date("2026-06-01 19:00")
for i in 0..<stadiumCount {
// Distribute stadiums geographically (rough US coverage)
let lat = 30.0 + Double(i % 20) * 1.0 // 30-50 latitude
let lon = -120.0 + Double(i / 20) * 5.0 // -120 to -70 longitude
let stadium = makeStadium(
city: "City\(i)",
lat: lat,
lon: lon
)
stadiums[stadium.id] = stadium
}
// Create games distributed across stadiums and days
var games: [Game] = []
let stadiumIds = Array(stadiums.keys)
for i in 0..<gameCount {
// Distribute games across days
let dayOffset = Double(i * daysSpan) / Double(gameCount)
let hoursOffset = Double(i % 3) * 3.0 // Vary game times within day
let gameTime = baseDate.addingTimeInterval(dayOffset * 24 * 3600 + hoursOffset * 3600)
// Pick a stadium (cycle through them)
let stadiumId = stadiumIds[i % stadiumIds.count]
let game = makeGame(stadiumId: stadiumId, startTime: gameTime)
games.append(game)
}
return (games, stadiums)
}
@Test("Performance: 1000 games completes in under 2 seconds")
func performance_1000Games_CompletesInTime() {
let (games, stadiums) = generateLargeDataset(gameCount: 1000, stadiumCount: 50, daysSpan: 30)
let start = ContinuousClock.now
let routes = GameDAGRouter.findRoutes(
games: games,
stadiums: stadiums,
constraints: .default
)
let elapsed = start.duration(to: .now)
#expect(routes.count > 0, "Should return routes")
#expect(elapsed < .seconds(2), "Should complete within 2 seconds, actual: \(elapsed)")
}
@Test("Performance: 5000 games completes in under 10 seconds")
func performance_5000Games_CompletesInTime() {
let (games, stadiums) = generateLargeDataset(gameCount: 5000, stadiumCount: 100, daysSpan: 60)
let start = ContinuousClock.now
let routes = GameDAGRouter.findRoutes(
games: games,
stadiums: stadiums,
constraints: .default
)
let elapsed = start.duration(to: .now)
#expect(routes.count > 0, "Should return routes")
#expect(elapsed < .seconds(10), "Should complete within 10 seconds, actual: \(elapsed)")
}
@Test("Performance: 10000 games completes in under 30 seconds")
func performance_10000Games_CompletesInTime() {
let (games, stadiums) = generateLargeDataset(gameCount: 10000, stadiumCount: 150, daysSpan: 90)
let start = ContinuousClock.now
let routes = GameDAGRouter.findRoutes(
games: games,
stadiums: stadiums,
constraints: .default
)
let elapsed = start.duration(to: .now)
#expect(routes.count > 0, "Should return routes")
#expect(elapsed < .seconds(30), "Should complete within 30 seconds, actual: \(elapsed)")
}
@Test("Performance: 10000 games does not cause memory issues")
func performance_10000Games_NoMemorySpike() {
let (games, stadiums) = generateLargeDataset(gameCount: 10000, stadiumCount: 150, daysSpan: 90)
// Run the algorithm
let routes = GameDAGRouter.findRoutes(
games: games,
stadiums: stadiums,
constraints: .default
)
// Verify routes returned (not OOM)
#expect(routes.count > 0, "Should return routes without memory crash")
#expect(routes.count <= 100, "Should return reasonable number of routes")
}
}