ThreatSourceLibaray/docs/test_result/performance_optimization_next_steps.md

7.9 KiB
Raw Permalink Blame History

威胁源仿真库性能优化 - 下一步行动计划

基于最新测试结果的分析 (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监控工具

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

<PropertyGroup>
  <ServerGarbageCollection>true</ServerGarbageCollection>
  <ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
</PropertyGroup>

第二优先级:对象生命周期优化

2.1 诊断中等生命周期对象

// 添加到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使用可能导致中等生命周期对象

// 替换现有的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 批量处理优化

// 批量更新实体,减少虚函数调用开销
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优化距离计算

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);
        }
    }
}

性能测试增强建议

增加更详细的诊断

[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周验证和调优

  • 大规模场景测试
  • 性能回归测试
  • 文档更新

注意: 当前的性能表现已经相当不错,建议采用谨慎的增量优化策略,避免过度优化导致代码复杂度上升。