588 lines
12 KiB
Markdown
588 lines
12 KiB
Markdown
# Phase 4 性能测试计划
|
||
|
||
**阶段**: Week 11-12 - 性能优化与基准测试
|
||
**测试负责人**: 测试工程师
|
||
**更新日期**: 2026-03-07
|
||
**状态**: 🟡 进行中
|
||
|
||
---
|
||
|
||
## 📊 性能目标
|
||
|
||
### 核心性能指标
|
||
|
||
| 指标 | 目标值 | 最低可接受 | 测量方法 |
|
||
|------|-------|-----------|---------|
|
||
| 渲染帧率 (100 元件) | 60fps | 60fps | Flutter DevTools |
|
||
| 渲染帧率 (500 元件) | 60fps | 55fps | Flutter DevTools |
|
||
| 渲染帧率 (1000 元件) | 60fps | 50fps | Flutter DevTools |
|
||
| 渲染帧率 (5000 元件) | 30fps | 24fps | Flutter DevTools |
|
||
| 冷启动时间 | <2s | <3s | Firebase Performance |
|
||
| 热启动时间 | <1s | <2s | Firebase Performance |
|
||
| 内存占用 (1000 元件) | <300MB | <500MB | Xcode Instruments / Android Profiler |
|
||
| 保存耗时 (1000 元件) | <1s | <2s | 代码埋点 |
|
||
| 加载耗时 (1000 元件) | <1s | <2s | 代码埋点 |
|
||
| 崩溃率 | <0.1% | <0.5% | Firebase Crashlytics |
|
||
| ANR 率 (Android) | <0.1% | <0.5% | Firebase Crashlytics |
|
||
|
||
---
|
||
|
||
## 🧪 性能测试场景
|
||
|
||
### PERF-001: 渲染性能基准测试
|
||
|
||
**优先级**: P0
|
||
**测试工具**: Flutter DevTools, PerformanceOverlay
|
||
|
||
**测试步骤**:
|
||
|
||
1. 打开性能监控
|
||
```dart
|
||
// main.dart 添加性能监控
|
||
import 'package:flutter/scheduler.dart';
|
||
|
||
void main() {
|
||
// ...
|
||
runApp(MyApp());
|
||
|
||
// 开启性能监控(仅调试模式)
|
||
if (kDebugMode) {
|
||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||
debugProfileBuildsEnabled = true;
|
||
debugProfilePaintsEnabled = true;
|
||
});
|
||
}
|
||
}
|
||
```
|
||
|
||
2. 创建不同规模的测试项目
|
||
|
||
| 项目名 | 元件数 | 连线数 | 用途 |
|
||
|-------|-------|-------|------|
|
||
| Test-Small | 50 | 30 | 基础性能 |
|
||
| Test-Medium | 200 | 150 | 常规使用 |
|
||
| Test-Large | 1000 | 800 | 性能基准 |
|
||
| Test-Extreme | 5000 | 4000 | 压力测试 |
|
||
|
||
3. 测量帧率
|
||
|
||
```
|
||
操作 目标帧率 测量时间
|
||
- 静态显示 60fps 10 秒
|
||
- 缓慢平移 60fps 10 秒
|
||
- 快速平移 60fps 10 秒
|
||
- 缓慢缩放 60fps 10 秒
|
||
- 快速缩放 60fps 10 秒
|
||
- 旋转 60fps 10 秒
|
||
```
|
||
|
||
4. 记录结果
|
||
|
||
| 项目规模 | 静态 | 平移 | 缩放 | 旋转 | 平均 |
|
||
|---------|------|------|------|------|------|
|
||
| 50 元件 | - | - | - | - | - |
|
||
| 200 元件 | - | - | - | - | - |
|
||
| 1000 元件 | - | - | - | - | - |
|
||
| 5000 元件 | - | - | - | - | - |
|
||
|
||
**验收标准**:
|
||
- [ ] 1000 元件场景平均帧率 ≥50fps
|
||
- [ ] 5000 元件场景平均帧率 ≥24fps
|
||
- [ ] 无明显掉帧或卡顿
|
||
|
||
---
|
||
|
||
### PERF-002: 内存性能测试
|
||
|
||
**优先级**: P0
|
||
**测试工具**: Xcode Instruments (iOS), Android Profiler (Android)
|
||
|
||
**测试步骤**:
|
||
|
||
1. 基线测量
|
||
```
|
||
应用启动后空闲状态内存:___ MB
|
||
```
|
||
|
||
2. 加载不同规模项目
|
||
|
||
| 操作 | 内存增量 | 峰值内存 | 释放后内存 |
|
||
|------|---------|---------|-----------|
|
||
| 加载 50 元件 | - | - | - |
|
||
| 加载 200 元件 | - | - | - |
|
||
| 加载 1000 元件 | - | - | - |
|
||
| 加载 5000 元件 | - | - | - |
|
||
|
||
3. 内存泄漏检测
|
||
|
||
```
|
||
操作 内存变化
|
||
- 打开/关闭项目 10 次 -
|
||
- 快速缩放 100 次 -
|
||
- 添加/删除元件 100 次 -
|
||
- 应用前后台切换 10 次 -
|
||
```
|
||
|
||
4. 长时间运行测试
|
||
|
||
```
|
||
运行时间 内存占用 备注
|
||
0 min - 初始
|
||
15 min - 持续编辑
|
||
30 min - 持续编辑
|
||
60 min - 持续编辑
|
||
```
|
||
|
||
**验收标准**:
|
||
- [ ] 1000 元件场景内存 <500MB
|
||
- [ ] 无明显内存泄漏(1 小时增长 <50MB)
|
||
- [ ] 内存释放正常
|
||
|
||
---
|
||
|
||
### PERF-003: 启动性能测试
|
||
|
||
**优先级**: P1
|
||
**测试工具**: Firebase Performance Monitoring
|
||
|
||
**测试步骤**:
|
||
|
||
1. 冷启动时间测量(应用完全关闭后首次启动)
|
||
|
||
```
|
||
测试次数 启动时间 备注
|
||
1 - 首次安装
|
||
2 - 第二次
|
||
3 - 第三次
|
||
4 - 第四次
|
||
5 - 第五次
|
||
平均 -
|
||
```
|
||
|
||
2. 热启动时间测量(应用在后台,切换到前台)
|
||
|
||
```
|
||
测试次数 启动时间 备注
|
||
1 -
|
||
2 -
|
||
3 -
|
||
4 -
|
||
5 -
|
||
平均 -
|
||
```
|
||
|
||
3. 启动流程分解
|
||
|
||
```
|
||
阶段 耗时
|
||
- 应用初始化 -
|
||
- Isar 数据库打开 -
|
||
- 主 Widget 构建 -
|
||
- 首页渲染完成 -
|
||
- 可交互状态 -
|
||
总计 -
|
||
```
|
||
|
||
**验收标准**:
|
||
- [ ] 冷启动时间 <3s
|
||
- [ ] 热启动时间 <2s
|
||
- [ ] 启动过程无白屏
|
||
|
||
---
|
||
|
||
### PERF-004: 存储性能测试
|
||
|
||
**优先级**: P1
|
||
**测试工具**: 代码埋点
|
||
|
||
**测试步骤**:
|
||
|
||
1. 保存性能
|
||
|
||
| 项目规模 | 保存耗时 | 文件大小 | 状态 |
|
||
|---------|---------|---------|------|
|
||
| 50 元件 | - | - | ⏳ |
|
||
| 200 元件 | - | - | ⏳ |
|
||
| 1000 元件 | - | - | ⏳ |
|
||
| 5000 元件 | - | - | ⏳ |
|
||
|
||
2. 加载性能
|
||
|
||
| 项目规模 | 加载耗时 | 文件大小 | 状态 |
|
||
|---------|---------|---------|------|
|
||
| 50 元件 | - | - | ⏳ |
|
||
| 200 元件 | - | - | ⏳ |
|
||
| 1000 元件 | - | - | ⏳ |
|
||
| 5000 元件 | - | - | ⏳ |
|
||
|
||
3. 云同步性能
|
||
|
||
| 操作 | 网络条件 | 耗时 | 状态 |
|
||
|------|---------|------|------|
|
||
| 上传 1MB | WiFi | - | ⏳ |
|
||
| 上传 1MB | 4G | - | ⏳ |
|
||
| 下载 1MB | WiFi | - | ⏳ |
|
||
| 下载 1MB | 4G | - | ⏳ |
|
||
|
||
**验收标准**:
|
||
- [ ] 1000 元件保存 <2s
|
||
- [ ] 1000 元件加载 <2s
|
||
- [ ] 云同步有进度提示
|
||
|
||
---
|
||
|
||
### PERF-005: 电池性能测试
|
||
|
||
**优先级**: P2
|
||
**测试工具**: 系统电池统计
|
||
|
||
**测试步骤**:
|
||
|
||
1. 正常使用场景
|
||
|
||
```
|
||
场景 10 分钟耗电
|
||
- 静态显示 -
|
||
- 持续编辑 -
|
||
- 频繁缩放 -
|
||
- 屏幕常亮 -
|
||
```
|
||
|
||
2. 低电量模式
|
||
|
||
```
|
||
模式 性能变化 备注
|
||
正常模式 100% -
|
||
省电模式 - 系统限制
|
||
低电量模式 - 应用适配
|
||
```
|
||
|
||
**验收标准**:
|
||
- [ ] 1 小时持续编辑耗电 <15%
|
||
- [ ] 低电量模式有适配
|
||
|
||
---
|
||
|
||
### PERF-006: 网络性能测试
|
||
|
||
**优先级**: P1
|
||
**测试工具**: Network Link Conditioner (iOS), Android Emulator Network
|
||
|
||
**测试场景**:
|
||
|
||
| 网络条件 | 延迟 | 带宽 | 测试项 | 预期结果 |
|
||
|---------|------|------|-------|---------|
|
||
| WiFi | 20ms | 100Mbps | 同步 | <5s |
|
||
| 4G | 100ms | 10Mbps | 同步 | <10s |
|
||
| 3G | 300ms | 1Mbps | 同步 | <30s |
|
||
| 2G | 1000ms | 50Kbps | 同步 | 超时提示 |
|
||
| 弱网 | 500ms+ | 波动 | 同步 | 不崩溃 |
|
||
| 断网 | - | 0 | 本地操作 | 正常 |
|
||
|
||
**验收标准**:
|
||
- [ ] 正常网络同步流畅
|
||
- [ ] 弱网有超时处理
|
||
- [ ] 断网可本地操作
|
||
|
||
---
|
||
|
||
## 🔧 性能优化技术
|
||
|
||
### 渲染优化
|
||
|
||
#### 1. 视口裁剪(Viewport Culling)
|
||
|
||
只绘制可见区域内的元件:
|
||
|
||
```dart
|
||
void _drawComponents(Canvas canvas, Size size) {
|
||
// 计算可见区域(考虑缩放和平移)
|
||
final visibleRect = _calculateVisibleRect(size);
|
||
|
||
// 只绘制可见区域内的元件
|
||
for (final component in components) {
|
||
if (_isVisible(visibleRect, component.bounds)) {
|
||
_drawComponent(canvas, component);
|
||
}
|
||
}
|
||
}
|
||
|
||
Rect _calculateVisibleRect(Size size) {
|
||
return Rect.fromLTWH(
|
||
-offset.dx / zoomLevel,
|
||
-offset.dy / zoomLevel,
|
||
size.width / zoomLevel,
|
||
size.height / zoomLevel,
|
||
);
|
||
}
|
||
```
|
||
|
||
#### 2. 分层渲染(Layer Rendering)
|
||
|
||
使用 Layer 隔离不同元素的重绘:
|
||
|
||
```dart
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return RepaintBoundary(
|
||
child: Stack(
|
||
children: [
|
||
// 网格层(静态,很少重绘)
|
||
RepaintBoundary(
|
||
child: CustomPaint(painter: GridPainter()),
|
||
),
|
||
// 元件层(中等频率)
|
||
RepaintBoundary(
|
||
child: CustomPaint(painter: ComponentPainter()),
|
||
),
|
||
// 交互层(高频重绘)
|
||
CustomPaint(painter: InteractionPainter()),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
```
|
||
|
||
#### 3. 离屏缓存(Off-screen Caching)
|
||
|
||
缓存静态内容:
|
||
|
||
```dart
|
||
Picture? _cachedPicture;
|
||
|
||
void _cacheComponents() {
|
||
final recorder = PictureRecorder();
|
||
final canvas = Canvas(recorder);
|
||
|
||
// 绘制到离屏
|
||
_drawComponentsToCanvas(canvas);
|
||
|
||
_cachedPicture = recorder.endRecording();
|
||
}
|
||
|
||
@override
|
||
void paint(Canvas canvas, Size size) {
|
||
if (_cachedPicture != null) {
|
||
// 使用缓存
|
||
canvas.drawPicture(_cachedPicture!);
|
||
} else {
|
||
// 实时绘制
|
||
_drawComponents(canvas);
|
||
}
|
||
}
|
||
```
|
||
|
||
### 内存优化
|
||
|
||
#### 1. 图片资源优化
|
||
|
||
```dart
|
||
// 使用适当分辨率的图片
|
||
Image.asset(
|
||
'assets/icons/component.png',
|
||
width: 24,
|
||
height: 24,
|
||
cacheWidth: 48, // 2x 分辨率
|
||
cacheHeight: 48,
|
||
)
|
||
```
|
||
|
||
#### 2. 及时释放资源
|
||
|
||
```dart
|
||
@override
|
||
void dispose() {
|
||
_cachedPicture?.dispose();
|
||
_animationController.dispose();
|
||
super.dispose();
|
||
}
|
||
```
|
||
|
||
#### 3. 使用 const 构造函数
|
||
|
||
```dart
|
||
// 使用 const 减少重建
|
||
const Icon(Icons.save)
|
||
const SizedBox(width: 8)
|
||
```
|
||
|
||
### 启动优化
|
||
|
||
#### 1. 延迟加载
|
||
|
||
```dart
|
||
// 非关键数据延迟加载
|
||
Future.delayed(Duration.zero, () {
|
||
_loadBackgroundData();
|
||
});
|
||
```
|
||
|
||
#### 2. 异步初始化
|
||
|
||
```dart
|
||
void main() async {
|
||
WidgetsFlutterBinding.ensureInitialized();
|
||
|
||
// 并行初始化
|
||
await Future.wait([
|
||
Firebase.initializeApp(),
|
||
Isar.open([...]),
|
||
AppConfig.init(),
|
||
]);
|
||
|
||
runApp(MyApp());
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 📈 性能监控
|
||
|
||
### Firebase Performance Monitoring
|
||
|
||
```dart
|
||
// pubspec.yaml
|
||
dependencies:
|
||
firebase_core: ^2.24.0
|
||
firebase_performance: ^0.9.3
|
||
|
||
// main.dart
|
||
import 'package:firebase_performance/firebase_performance.dart';
|
||
|
||
// 追踪自定义指标
|
||
final Trace saveTrace = FirebasePerformance.instance.newTrace('save_project');
|
||
await saveTrace.start();
|
||
|
||
// 执行保存操作
|
||
await _saveProject();
|
||
|
||
await saveTrace.stop();
|
||
|
||
// 记录自定义指标
|
||
final MetricHandle memoryMetric = FirebasePerformance.instance.newMetric('memory_usage');
|
||
memoryMetric.setValue(currentMemoryMB);
|
||
```
|
||
|
||
### 代码埋点
|
||
|
||
```dart
|
||
class PerformanceTracker {
|
||
static final Map<String, DateTime> _timers = {};
|
||
|
||
static void start(String label) {
|
||
_timers[label] = DateTime.now();
|
||
}
|
||
|
||
static void end(String label) {
|
||
final start = _timers[label];
|
||
if (start != null) {
|
||
final duration = DateTime.now().difference(start);
|
||
print('[$label] ${duration.inMilliseconds}ms');
|
||
_timers.remove(label);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 使用
|
||
PerformanceTracker.start('load_project');
|
||
await loadProject();
|
||
PerformanceTracker.end('load_project');
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 性能测试报告模板
|
||
|
||
### Mobile EDA 性能测试报告
|
||
|
||
**测试日期**: YYYY-MM-DD
|
||
**测试人员**: 测试工程师
|
||
**设备信息**: [设备型号/系统版本]
|
||
|
||
---
|
||
|
||
#### 渲染性能
|
||
|
||
| 场景 | 目标 | 实测 | 状态 |
|
||
|------|------|------|------|
|
||
| 100 元件静态 | 60fps | - | ⏳ |
|
||
| 100 元件平移 | 60fps | - | ⏳ |
|
||
| 1000 元件静态 | 60fps | - | ⏳ |
|
||
| 1000 元件平移 | 50fps | - | ⏳ |
|
||
| 5000 元件静态 | 30fps | - | ⏳ |
|
||
|
||
#### 内存性能
|
||
|
||
| 场景 | 目标 | 实测 | 状态 |
|
||
|------|------|------|------|
|
||
| 空闲状态 | <100MB | - | ⏳ |
|
||
| 1000 元件 | <500MB | - | ⏳ |
|
||
| 5000 元件 | <1GB | - | ⏳ |
|
||
| 1 小时运行 | 增长<50MB | - | ⏳ |
|
||
|
||
#### 启动性能
|
||
|
||
| 类型 | 目标 | 实测 | 状态 |
|
||
|------|------|------|------|
|
||
| 冷启动 | <3s | - | ⏳ |
|
||
| 热启动 | <2s | - | ⏳ |
|
||
|
||
#### 存储性能
|
||
|
||
| 操作 | 规模 | 目标 | 实测 | 状态 |
|
||
|------|------|------|------|------|
|
||
| 保存 | 1000 元件 | <2s | - | ⏳ |
|
||
| 加载 | 1000 元件 | <2s | - | ⏳ |
|
||
|
||
#### 崩溃率
|
||
|
||
| 指标 | 目标 | 实测 | 状态 |
|
||
|------|------|------|------|
|
||
| 崩溃率 | <0.1% | - | ⏳ |
|
||
| ANR 率 | <0.1% | - | ⏳ |
|
||
|
||
---
|
||
|
||
#### 性能问题汇总
|
||
|
||
| 问题描述 | 严重程度 | 优化建议 | 状态 |
|
||
|---------|---------|---------|------|
|
||
| - | - | - | ⏳ |
|
||
|
||
#### 优化建议
|
||
|
||
1. ...
|
||
2. ...
|
||
3. ...
|
||
|
||
---
|
||
|
||
**结论**: [通过/不通过]
|
||
|
||
---
|
||
|
||
## 📅 测试计划
|
||
|
||
### Week 11
|
||
|
||
| 日期 | 测试内容 | 负责人 |
|
||
|------|---------|-------|
|
||
| 周一 | PERF-001 渲染性能 | 测试工程师 |
|
||
| 周二 | PERF-002 内存性能 | 测试工程师 |
|
||
| 周三 | PERF-003 启动性能 | 测试工程师 |
|
||
| 周四 | PERF-004 存储性能 | 测试工程师 |
|
||
| 周五 | PERF-005/006 电池/网络 | 测试工程师 |
|
||
|
||
### Week 12
|
||
|
||
| 日期 | 测试内容 | 负责人 |
|
||
|------|---------|-------|
|
||
| 周一 | 性能问题修复验证 | 测试工程师 |
|
||
| 周二 | 回归测试 | 测试工程师 |
|
||
| 周三 | 性能基准报告 | 测试工程师 |
|
||
|
||
---
|
||
|
||
**文档维护**: 测试工程师
|
||
**最后更新**: 2026-03-07
|