ThreatSourceLibaray/docs/performance_optimization_next_steps.md

282 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 威胁源仿真库性能优化 - 下一步行动计划
## 基于最新测试结果的分析 (2024-12)
### 测试环境
- **配置**: 50个目标, 20个导弹, 30秒测试
- **模式**: Release模式50fps目标
- **平台**: .NET Core (具体版本待确认)
## 当前性能状况
### ✅ 已达到优秀水平的指标
1. **帧时间**: 平均0.36ms (目标<1ms)
2. **内存管理**: 增长率0.22MB/s无泄漏迹象
3. **基本GC性能**: Gen0频率1.3次/在可接受范围
### ⚠️ 需要重点关注的问题
#### 1. GC暂停问题 (关键)
- **症状**: 最大帧时间20.57ms99%分位数5.71ms
- **影响**: 造成明显的性能尖刺用户可感知的卡顿
- **可能原因**:
- Gen1/Gen2 GC的阻塞式回收
- 大对象堆(LOH)的压缩操作
- 终结器队列阻塞
#### 2. 异常的GC模式
- **症状**: Gen1(1.1次/)和Gen2(1.1次/)频率异常高
- **正常情况**: 应该是Gen0 >> Gen1 >> Gen2的递减关系
- **可能原因**:
- 存在大量中等生命周期对象(几帧到几秒)
- LOH对象分配导致Gen2触发
- 跨代引用较多
## 详细优化策略
### 第一优先级GC暂停诊断和优化
#### 1.1 添加GC监控工具
```csharp
public class GCMonitor
{
private static volatile bool _monitoring = false;
private static readonly StringBuilder _gcLog = new StringBuilder();
public static void StartMonitoring()
{
if (_monitoring) return;
_monitoring = true;
// 注册GC通知
GC.RegisterForFullGCNotification(10, 10);
Task.Run(MonitorGCEvents);
}
private static void MonitorGCEvents()
{
while (_monitoring)
{
// 监控即将发生的GC
if (GC.WaitForFullGCApproach() == GCNotificationStatus.Succeeded)
{
var sw = Stopwatch.StartNew();
var beforeMemory = GC.GetTotalMemory(false);
// 等待GC完成
if (GC.WaitForFullGCComplete() == GCNotificationStatus.Succeeded)
{
sw.Stop();
var afterMemory = GC.GetTotalMemory(false);
Debug.WriteLine($"[GC] 耗时: {sw.ElapsedMilliseconds}ms, " +
$"回收: {(beforeMemory - afterMemory) / 1024.0:F1}KB, " +
$"剩余: {afterMemory / 1024.0:F1}KB");
}
}
}
}
}
```
#### 1.2 大对象分配检查
需要审查以下可能分配大对象的代码:
- `InfraredTargetRecognizer.cs` - 图像处理数组
- `MillimeterWaveGuidanceSystem.cs` - 信号处理缓冲区
- `SimulationManager.cs` - 批量数据处理
#### 1.3 服务器GC模式考虑
如果是桌面应用考虑启用服务器GC
```xml
<PropertyGroup>
<ServerGarbageCollection>true</ServerGarbageCollection>
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
</PropertyGroup>
```
### 第二优先级:对象生命周期优化
#### 2.1 诊断中等生命周期对象
```csharp
// 添加到SimulationManager
private readonly Dictionary<string, WeakReference> _objectTracker = new();
public void TrackObject(string category, object obj)
{
#if DEBUG
_objectTracker[$"{category}_{DateTime.Now.Ticks}"] = new WeakReference(obj);
#endif
}
public void ReportObjectLifetime()
{
#if DEBUG
int aliveCount = _objectTracker.Values.Count(wr => wr.IsAlive);
Debug.WriteLine($"[对象追踪] 活跃对象: {aliveCount}/{_objectTracker.Count}");
#endif
}
```
#### 2.2 优化制导系统历史数据
当前的Queue<T>使用可能导致中等生命周期对象:
```csharp
// 替换现有的Queue历史记录
public class OptimizedGuidanceHistory
{
private readonly double[] _snrHistory;
private readonly bool[] _detectionHistory;
private int _currentIndex = 0;
private int _count = 0;
public OptimizedGuidanceHistory(int capacity)
{
_snrHistory = new double[capacity];
_detectionHistory = new bool[capacity];
}
public void AddSample(double snr, bool detected)
{
_snrHistory[_currentIndex] = snr;
_detectionHistory[_currentIndex] = detected;
_currentIndex = (_currentIndex + 1) % _snrHistory.Length;
if (_count < _snrHistory.Length) _count++;
}
// 零分配的统计计算
public (double avgSnr, double successRate) GetStatistics()
{
if (_count == 0) return (0.0, 0.0);
double sumSnr = 0.0;
int successCount = 0;
for (int i = 0; i < _count; i++)
{
sumSnr += _snrHistory[i];
if (_detectionHistory[i]) successCount++;
}
return (sumSnr / _count, (double)successCount / _count);
}
}
```
### 第三优先级:进一步性能提升
#### 3.1 批量处理优化
```csharp
// 批量更新实体,减少虚函数调用开销
private void BatchUpdateEntities(List<SimulationElement> elements, double deltaTime)
{
// 按类型分组利用CPU缓存局部性
var missiles = new List<BaseMissile>();
var targets = new List<Tank>();
var sensors = new List<SensorBase>();
foreach (var element in elements)
{
switch (element)
{
case BaseMissile missile: missiles.Add(missile); break;
case Tank tank: targets.Add(tank); break;
case SensorBase sensor: sensors.Add(sensor); break;
}
}
// 分类型批量更新
Parallel.ForEach(missiles, missile => missile.Update(deltaTime));
Parallel.ForEach(targets, target => target.Update(deltaTime));
Parallel.ForEach(sensors, sensor => sensor.Update(deltaTime));
}
```
#### 3.2 SIMD优化距离计算
```csharp
public static class VectorizedMath
{
public static void CalculateDistancesBatch(
ReadOnlySpan<Vector3D> positions1,
ReadOnlySpan<Vector3D> positions2,
Span<double> results)
{
for (int i = 0; i < positions1.Length; i++)
{
var delta = positions1[i] - positions2[i];
results[i] = Math.Sqrt(delta.X * delta.X + delta.Y * delta.Y + delta.Z * delta.Z);
}
}
}
```
## 性能测试增强建议
### 增加更详细的诊断
```csharp
[Test]
public void DetailedPerformanceTest()
{
// 启用GC监控
GCMonitor.StartMonitoring();
// 记录每种GC的详细信息
var gcCounts = new int[3];
for (int frame = 0; frame < 1500; frame++)
{
var before = new[] { GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2) };
simulationManager.Update(0.02);
var after = new[] { GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2) };
for (int gen = 0; gen < 3; gen++)
{
if (after[gen] > before[gen])
{
Debug.WriteLine($"[帧{frame}] Gen{gen} GC触发");
}
}
}
}
```
## 成功标准
### 短期目标 (2-4周)
- [ ] GC最大暂停时间 < 10ms
- [ ] 99%分位数帧时间 < 2ms
- [ ] Gen1/Gen2 GC频率 < 0.5次/
### 中期目标 (1-2个月)
- [ ] 支持100个目标 + 50个导弹的场景
- [ ] 平均帧时间保持 < 0.5ms
- [ ] 内存增长率 < 0.1MB/s
### 工具和方法
1. **Visual Studio诊断工具** - 内存使用分析
2. **dotMemory** - 对象分配和生命周期分析
3. **PerfView** - ETW事件跟踪GC详细分析
4. **BenchmarkDotNet** - 微基准测试
## 实施时间表
### 第1-2周诊断阶段
- 集成GC监控工具
- 使用PerfView分析GC行为
- 识别大对象和中等生命周期对象的来源
### 第3-4周优化实施
- 实施识别出的具体优化
- 增强性能测试套件
- 验证优化效果
### 第5-6周验证和调优
- 大规模场景测试
- 性能回归测试
- 文档更新
---
**注意**: 当前的性能表现已经相当不错建议采用谨慎的增量优化策略避免过度优化导致代码复杂度上升