/** * 大电路性能压测基准 * * 测试场景:1000/5000/10000 元件设计 * 测试指标:启动时间、帧率、内存占用、操作延迟 * 瓶颈分析:渲染/数据/手势识别 * * @version 1.0.0 * @date 2026-03-07 * @author 性能优化专家 */ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'dart:math' as math; import '../../lib/domain/models/core_models.dart'; import '../../lib/presentation/components/editable_canvas.dart'; import '../../lib/domain/managers/selection_manager.dart'; // ============================================================================ // 性能指标模型 // ============================================================================ /// 性能测试结果 class PerformanceMetrics { final int componentCount; final Duration startupTime; final double averageFPS; final int minFPS; final int maxFPS; final int memoryUsageMB; final Duration panLatency; final Duration zoomLatency; final Duration tapLatency; final Duration dragLatency; final String bottleneck; final Map details; PerformanceMetrics({ required this.componentCount, required this.startupTime, required this.averageFPS, required this.minFPS, required this.maxFPS, required this.memoryUsageMB, required this.panLatency, required this.zoomLatency, required this.tapLatency, required this.dragLatency, required this.bottleneck, required this.details, }); @override String toString() { return ''' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 性能报告 - ${componentCount} 元件 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 启动时间:${startupTime.inMilliseconds}ms 帧率:${averageFPS.toStringAsFixed(1)} FPS (min: $minFPS, max: $maxFPS) 内存占用:${memoryUsageMB}MB 操作延迟: - 平移:${panLatency.inMilliseconds}ms - 缩放:${zoomLatency.inMilliseconds}ms - 点击:${tapLatency.inMilliseconds}ms - 拖拽:${dragLatency.inMilliseconds}ms 瓶颈分析:$bottleneck ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ '''; } Map toJson() { return { 'componentCount': componentCount, 'startupTime': startupTime.inMilliseconds, 'averageFPS': averageFPS, 'minFPS': minFPS, 'maxFPS': maxFPS, 'memoryUsageMB': memoryUsageMB, 'panLatency': panLatency.inMilliseconds, 'zoomLatency': zoomLatency.inMilliseconds, 'tapLatency': tapLatency.inMilliseconds, 'dragLatency': dragLatency.inMilliseconds, 'bottleneck': bottleneck, 'details': details, }; } } // ============================================================================ // 测试数据生成器 // ============================================================================ /// 测试电路生成器 class TestCircuitGenerator { static Design generateDesign({ required int componentCount, String name = 'Performance Test', }) { final timestamp = DateTime.now().millisecondsSinceEpoch; final random = math.Random(42); // 固定种子保证可重复性 final components = {}; final nets = {}; // 生成元件 for (int i = 0; i < componentCount; i++) { final id = 'comp_$i'; final x = random.nextInt(10000) * 1000; // 0-10000mm final y = random.nextInt(10000) * 1000; final pinCount = 4 + random.nextInt(12); // 4-16 pins final pins = []; for (int p = 0; p < pinCount; p++) { pins.add(PinReference( pinId: 'pin_$p', name: 'P$p', x: (p % 4) * 100000 - 150000, y: (p ~/ 4) * 100000 - 150000, rotation: 0, electricalType: PinElectricalType.passive, )); } components[id] = Component( id: id, name: 'U$i', type: ComponentType.ic, value: 'TEST_${i % 100}', footprint: Footprint( id: 'fp_$i', name: 'TEST_FP', pads: [], metadata: Metadata( createdAt: timestamp, updatedAt: timestamp, ), ), position: Position2D(x: x, y: y), layerId: 'layer_signal_1', rotation: 0, mirror: MirrorState.none, pins: pins, metadata: Metadata( createdAt: timestamp, updatedAt: timestamp, ), ); } // 生成网络连接(每个元件随机连接 1-3 个其他元件) int netIndex = 0; components.forEach((id, component) { final connectionCount = 1 + random.nextInt(3); for (int c = 0; c < connectionCount; c++) { final targetId = components.keys.elementAt( random.nextInt(components.length), ); if (targetId == id) continue; final targetComponent = components[targetId]!; final netId = 'net_${netIndex++}'; nets[netId] = Net( id: netId, name: 'N$netIndex', type: NetType.signal, connections: [ ConnectionPoint( id: '$id:pin_0', type: ConnectionType.pin, componentId: id, pinId: 'pin_0', position: Position2D( x: component.position.x + component.pins[0].x, y: component.position.y + component.pins[0].y, ), layerId: component.layerId, ), ConnectionPoint( id: '$targetId:pin_0', type: ConnectionType.pin, componentId: targetId, pinId: 'pin_0', position: Position2D( x: targetComponent.position.x + targetComponent.pins[0].x, y: targetComponent.position.y + targetComponent.pins[0].y, ), layerId: targetComponent.layerId, ), ], metadata: Metadata( createdAt: timestamp, updatedAt: timestamp, ), ); } }); return Design( id: 'perf_test_design', name: name, version: '1.0.0', components: components, nets: nets, layers: { 'layer_signal_1': Layer( id: 'layer_signal_1', name: 'Signal Layer 1', type: LayerType.signal, stackupOrder: 1, metadata: Metadata( createdAt: timestamp, updatedAt: timestamp, ), ), }, designRules: DesignRules(), createdAt: timestamp, updatedAt: timestamp, ); } } // ============================================================================ // 性能测试工具 // ============================================================================ /// FPS 计数器 class FPSCounter { final List _frameTimes = []; DateTime? _lastFrameTime; int _frameCount = 0; void markFrame() { final now = DateTime.now(); if (_lastFrameTime != null) { _frameTimes.add(now.difference(_lastFrameTime!).inMilliseconds); if (_frameTimes.length > 300) { _frameTimes.removeAt(0); } } _lastFrameTime = now; _frameCount++; } double get averageFPS { if (_frameTimes.isEmpty) return 0.0; final avgFrameTime = _frameTimes.reduce((a, b) => a + b) / _frameTimes.length; return avgFrameTime > 0 ? 1000.0 / avgFrameTime : 0.0; } int get minFPS { if (_frameTimes.isEmpty) return 0; final maxFrameTime = _frameTimes.reduce(math.max); return maxFrameTime > 0 ? (1000.0 / maxFrameTime).floor() : 0; } int get maxFPS { if (_frameTimes.isEmpty) return 0; final minFrameTime = _frameTimes.reduce(math.min); return minFrameTime > 0 ? (1000.0 / minFrameTime).floor() : 0; } void reset() { _frameTimes.clear(); _lastFrameTime = null; _frameCount = 0; } } // ============================================================================ // 基准测试 // ============================================================================ void main() { group('大电路性能基准测试', () { testWidgets('1000 元件 - 启动性能', (WidgetTester tester) async { final design = TestCircuitGenerator.generateDesign(componentCount: 1000); final selectionManager = SelectionManager(); final stopwatch = Stopwatch()..start(); await tester.pumpWidget( MaterialApp( home: Scaffold( body: EditableCanvas( design: design, onDesignChanged: (newDesign) {}, selectionManager: selectionManager, ), ), ), ); await tester.pumpAndSettle(); stopwatch.stop(); final startupTime = stopwatch.elapsed; print('✓ 1000 元件启动时间:${startupTime.inMilliseconds}ms'); expect(startupTime.inMilliseconds, lessThan(3000), reason: '1000 元件启动时间应小于 3 秒'); }); testWidgets('1000 元件 - 平移性能', (WidgetTester tester) async { final design = TestCircuitGenerator.generateDesign(componentCount: 1000); final selectionManager = SelectionManager(); await tester.pumpWidget( MaterialApp( home: Scaffold( body: EditableCanvas( design: design, onDesignChanged: (newDesign) {}, selectionManager: selectionManager, ), ), ), ); await tester.pumpAndSettle(); final fpsCounter = FPSCounter(); final stopwatch = Stopwatch(); // 执行平移操作 stopwatch.start(); final gesture = await tester.startGesture(const Offset(200, 200)); for (int i = 0; i < 10; i++) { await gesture.moveBy(const Offset(50, 0)); await tester.pump(); fpsCounter.markFrame(); } await gesture.up(); stopwatch.stop(); final avgLatency = stopwatch.elapsedMilliseconds ~/ 10; print('✓ 1000 元件平移延迟:${avgLatency}ms, FPS: ${fpsCounter.averageFPS.toStringAsFixed(1)}'); expect(avgLatency, lessThan(50), reason: '平移延迟应小于 50ms'); expect(fpsCounter.averageFPS, greaterThan(30), reason: '帧率应大于 30 FPS'); }); testWidgets('5000 元件 - 启动性能', (WidgetTester tester) async { final design = TestCircuitGenerator.generateDesign(componentCount: 5000); final selectionManager = SelectionManager(); final stopwatch = Stopwatch()..start(); await tester.pumpWidget( MaterialApp( home: Scaffold( body: EditableCanvas( design: design, onDesignChanged: (newDesign) {}, selectionManager: selectionManager, ), ), ), ); await tester.pumpAndSettle(); stopwatch.stop(); final startupTime = stopwatch.elapsed; print('✓ 5000 元件启动时间:${startupTime.inMilliseconds}ms'); // 5000 元件允许更长的启动时间 expect(startupTime.inMilliseconds, lessThan(10000), reason: '5000 元件启动时间应小于 10 秒'); }); testWidgets('10000 元件 - 启动性能', (WidgetTester tester) async { final design = TestCircuitGenerator.generateDesign(componentCount: 10000); final selectionManager = SelectionManager(); final stopwatch = Stopwatch()..start(); await tester.pumpWidget( MaterialApp( home: Scaffold( body: EditableCanvas( design: design, onDesignChanged: (newDesign) {}, selectionManager: selectionManager, ), ), ), ); await tester.pumpAndSettle(); stopwatch.stop(); final startupTime = stopwatch.elapsed; print('✓ 10000 元件启动时间:${startupTime.inMilliseconds}ms'); // 10000 元件需要优化,这里先记录基线 print('⚠ 10000 元件启动时间基线:${startupTime.inMilliseconds}ms (待优化)'); }); test('生成性能基准报告', () { // 这是一个示例报告生成测试 final metrics = PerformanceMetrics( componentCount: 1000, startupTime: const Duration(milliseconds: 1500), averageFPS: 55.5, minFPS: 45, maxFPS: 60, memoryUsageMB: 128, panLatency: const Duration(milliseconds: 16), zoomLatency: const Duration(milliseconds: 20), tapLatency: const Duration(milliseconds: 8), dragLatency: const Duration(milliseconds: 24), bottleneck: '渲染性能', details: { 'renderTime': 12, 'layoutTime': 4, 'gestureTime': 2, }, ); print(metrics); print('JSON: ${metrics.toJson()}'); }); }); }