ThreatSourceLibaray/docs/project/performance_optimization_examples.md

18 KiB
Raw Blame History

C# 威胁源库性能优化实施示例

示例1SimulationManager对象池优化

原始代码问题

// ThreatSource/src/Simulation/SimulationManager.cs 当前实现
private void UpdateSimulation(double deltaTime)
{
    // 🔴 问题每帧创建新的List触发GC
    List<SimulationElement> activeElements = entities.Values
        .Cast<SimulationElement>()
        .Where(e => e.IsActive)
        .ToList();

    foreach (var element in activeElements)
    {
        element.Update(deltaTime);
    }
}

private void CheckHits()
{
    // 🔴 问题每帧创建多个List和复杂LINQ查询
    var activeMissiles = entities.Values.OfType<BaseMissile>().Where(e => e.IsActive).ToList();
    var activeTargets = entities.Values.OfType<Tank>().Where(e => e.IsActive).ToList();
    var hitEvents = new List<(Tank tank, BaseMissile missile, double damage)>();
    
    foreach (var missile in activeMissiles)
    {
        foreach (var target in activeTargets)
        {
            // 检测逻辑...
        }
    }
}

优化后的实现

步骤1创建对象池基础设施

// 新文件ThreatSource/src/Utils/ObjectPools.cs
using Microsoft.Extensions.ObjectPool;

namespace ThreatSource.Utils
{
    /// <summary>
    /// 仿真系统专用对象池管理器
    /// </summary>
    public class SimulationObjectPools
    {
        private readonly ObjectPool<List<SimulationElement>> _elementListPool;
        private readonly ObjectPool<List<BaseMissile>> _missileListPool;
        private readonly ObjectPool<List<Tank>> _tankListPool;
        private readonly ObjectPool<List<(Tank, BaseMissile, double)>> _hitEventPool;

        public SimulationObjectPools()
        {
            var provider = new DefaultObjectPoolProvider();
            
            _elementListPool = provider.Create(new ListPooledObjectPolicy<SimulationElement>(1000));
            _missileListPool = provider.Create(new ListPooledObjectPolicy<BaseMissile>(100));
            _tankListPool = provider.Create(new ListPooledObjectPolicy<Tank>(100));
            _hitEventPool = provider.Create(new ListPooledObjectPolicy<(Tank, BaseMissile, double)>(50));
        }

        public List<SimulationElement> GetElementList() => _elementListPool.Get();
        public void ReturnElementList(List<SimulationElement> list) => _elementListPool.Return(list);

        public List<BaseMissile> GetMissileList() => _missileListPool.Get();
        public void ReturnMissileList(List<BaseMissile> list) => _missileListPool.Return(list);

        public List<Tank> GetTankList() => _tankListPool.Get();
        public void ReturnTankList(List<Tank> list) => _tankListPool.Return(list);

        public List<(Tank, BaseMissile, double)> GetHitEventList() => _hitEventPool.Get();
        public void ReturnHitEventList(List<(Tank, BaseMissile, double)> list) => _hitEventPool.Return(list);
    }

    /// <summary>
    /// List的对象池策略
    /// </summary>
    public class ListPooledObjectPolicy<T> : IPooledObjectPolicy<List<T>>
    {
        private readonly int _initialCapacity;

        public ListPooledObjectPolicy(int initialCapacity = 100)
        {
            _initialCapacity = initialCapacity;
        }

        public List<T> Create()
        {
            return new List<T>(_initialCapacity);
        }

        public bool Return(List<T> obj)
        {
            if (obj == null) return false;
            
            // 清空但保留容量
            obj.Clear();
            
            // 如果List过大丢弃它以避免内存泄漏
            return obj.Capacity <= _initialCapacity * 4;
        }
    }
}

步骤2优化SimulationManager

// 修改ThreatSource/src/Simulation/SimulationManager.cs
public class SimulationManager : ISimulationManager
{
    // 新增:对象池
    private readonly SimulationObjectPools _objectPools;
    
    // 现有代码...
    private readonly Dictionary<string, object> entities = new();
    private readonly object _lock = new();

    public SimulationManager()
    {
        _objectPools = new SimulationObjectPools();
        // 其他初始化...
    }

    // ✅ 优化后的UpdateSimulation方法
    private void UpdateSimulation(double deltaTime)
    {
        var activeElements = _objectPools.GetElementList();
        try
        {
            // 收集活跃实体避免LINQ和ToList
            lock (_lock)
            {
                foreach (var entity in entities.Values)
                {
                    if (entity is SimulationElement element && element.IsActive)
                    {
                        activeElements.Add(element);
                    }
                }
            }

            // 更新实体
            for (int i = 0; i < activeElements.Count; i++)
            {
                try
                {
                    activeElements[i].Update(deltaTime);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"更新实体 {activeElements[i].Id} 时发生错误: {ex.Message}");
                }
            }
        }
        finally
        {
            _objectPools.ReturnElementList(activeElements);
        }
    }

    // ✅ 优化后的CheckHits方法  
    private void CheckHits()
    {
        var activeMissiles = _objectPools.GetMissileList();
        var activeTargets = _objectPools.GetTankList();
        var hitEvents = _objectPools.GetHitEventList();
        
        try
        {
            // 收集活跃导弹和目标避免LINQ
            lock (_lock)
            {
                foreach (var entity in entities.Values)
                {
                    switch (entity)
                    {
                        case BaseMissile missile when missile.IsActive:
                            activeMissiles.Add(missile);
                            break;
                        case Tank tank when tank.IsActive:
                            activeTargets.Add(tank);
                            break;
                    }
                }
            }

            Debug.WriteLine($"活动导弹数量: {activeMissiles.Count}");
            Debug.WriteLine($"活动目标数量: {activeTargets.Count}");

            // 检测命中使用for循环避免枚举器分配
            for (int i = 0; i < activeMissiles.Count; i++)
            {
                var missile = activeMissiles[i];
                for (int j = 0; j < activeTargets.Count; j++)
                {
                    var target = activeTargets[j];
                    double distance = Vector3D.Distance(missile.KState.Position, target.KState.Position);
                    
                    if (distance <= missile.Properties.ExplosionRadius)
                    {
                        double damage = CalculateDamage(missile, target, distance);
                        hitEvents.Add((target, missile, damage));
                    }
                }
            }

            // 处理命中事件
            for (int i = 0; i < hitEvents.Count; i++)
            {
                var (target, missile, damage) = hitEvents[i];
                ProcessHit(target, missile, damage);
            }
        }
        finally
        {
            _objectPools.ReturnMissileList(activeMissiles);
            _objectPools.ReturnTankList(activeTargets);
            _objectPools.ReturnHitEventList(hitEvents);
        }
    }
}

示例2事件系统零分配优化

原始代码问题

// 当前的事件发布实现
public void PublishEvent<T>(T evt) where T : class
{
    // 🔴 问题每次都创建ToList()副本
    if (eventHandlers.TryGetValue(actualType, out var actualHandlers))
    {
        var handlers = actualHandlers.ToList(); // 分配新List
        foreach (var handler in handlers)       // foreach分配枚举器
        {
            handler.DynamicInvoke(evt);         // DynamicInvoke造成装箱
        }
    }
}

优化后的实现

// ✅ 零分配的事件发布
public void PublishEvent<T>(T evt) where T : class
{
    if (evt == null) throw new ArgumentNullException(nameof(evt));
    
    var eventType = typeof(T);
    
    if (eventHandlers.TryGetValue(eventType, out var handlers))
    {
        // 使用for循环避免枚举器分配
        // 捕获Count避免重复调用
        int handlerCount = handlers.Count;
        for (int i = 0; i < handlerCount; i++)
        {
            try
            {
                // 直接强制转换避免DynamicInvoke
                if (handlers[i] is Action<T> typedHandler)
                {
                    typedHandler.Invoke(evt);
                }
                else
                {
                    // 回退到DynamicInvoke少数情况
                    handlers[i].DynamicInvoke(evt);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"[事件] 处理异常: {ex.Message}");
            }
        }
    }
}

示例3红外图像处理优化

原始代码问题

// ThreatSource/src/Guidance/InfraredTargetRecognizer.cs
public List<Blob> PerformConnectedComponentAnalysis(InfraredImage image)
{
    // 🔴 问题:每次都创建新的集合
    List<Blob> blobs = new List<Blob>();
    Queue<(int x, int y)> queue = new Queue<(int x, int y)>();
    
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            if (!visited[y, x] && image.GetIntensity(y, x) > threshold)
            {
                var currentBlob = new Blob
                {
                    Pixels = [], // 🔴 每个Blob都创建新List
                };
                // ... 处理逻辑
            }
        }
    }
    return blobs;
}

优化后的实现

// 新增:图像处理对象池
public class ImageProcessingPools
{
    private readonly ObjectPool<List<Blob>> _blobListPool;
    private readonly ObjectPool<Queue<(int, int)>> _pixelQueuePool;
    private readonly ObjectPool<List<(int, int)>> _pixelListPool;
    private readonly ObjectPool<bool[,]> _visitedArrayPool;

    public ImageProcessingPools()
    {
        var provider = new DefaultObjectPoolProvider();
        _blobListPool = provider.Create<List<Blob>>();
        _pixelQueuePool = provider.Create<Queue<(int, int)>>();
        _pixelListPool = provider.Create<List<(int, int)>>();
        _visitedArrayPool = provider.Create(new VisitedArrayPolicy());
    }

    // ✅ 池化的图像分割方法
    public List<Blob> PerformConnectedComponentAnalysis(InfraredImage image)
    {
        int width = image.Width;
        int height = image.Height;
        
        var blobs = _blobListPool.Get();
        var queue = _pixelQueuePool.Get();
        var visited = GetVisitedArray(width, height);
        
        try
        {
            double threshold = CalculateThreshold(image);
            
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    if (!visited[y, x] && image.GetIntensity(y, x) > threshold)
                    {
                        var pixelList = _pixelListPool.Get();
                        try
                        {
                            var currentBlob = ProcessBlob(x, y, image, visited, queue, pixelList, threshold);
                            blobs.Add(currentBlob);
                        }
                        finally
                        {
                            _pixelListPool.Return(pixelList);
                        }
                    }
                }
            }
            
            // 返回副本,调用者拥有所有权
            return new List<Blob>(blobs);
        }
        finally
        {
            _blobListPool.Return(blobs);
            _pixelQueuePool.Return(queue);
            ReturnVisitedArray(visited);
        }
    }

    private Blob ProcessBlob(int startX, int startY, InfraredImage image, bool[,] visited, 
                           Queue<(int, int)> queue, List<(int, int)> pixelList, double threshold)
    {
        int width = image.Width;
        int height = image.Height;
        
        var blob = new Blob
        {
            Label = GetNextBlobLabel(),
            MinX = startX, MinY = startY, MaxX = startX, MaxY = startY
        };

        queue.Enqueue((startX, startY));
        visited[startY, startX] = true;

        while (queue.Count > 0)
        {
            var (x, y) = queue.Dequeue();
            pixelList.Add((x, y));

            // 更新边界框
            blob.MinX = Math.Min(blob.MinX, x);
            blob.MinY = Math.Min(blob.MinY, y);
            blob.MaxX = Math.Max(blob.MaxX, x);
            blob.MaxY = Math.Max(blob.MaxY, y);

            // 检查4-邻域(使用局部数组避免分配)
            CheckNeighbor(x, y + 1, width, height, image, visited, queue, threshold);
            CheckNeighbor(x, y - 1, width, height, image, visited, queue, threshold);
            CheckNeighbor(x + 1, y, width, height, image, visited, queue, threshold);
            CheckNeighbor(x - 1, y, width, height, image, visited, queue, threshold);
        }

        // 复制像素列表到Blob调用者拥有
        blob.Pixels = new List<(int, int)>(pixelList);
        return blob;
    }
}

示例4制导系统历史数据优化

原始代码问题

// 多个制导系统中的问题
private readonly Queue<bool> activeDetectionHistory = new();
private readonly Queue<double> lockSnrHistory = new();

// 每帧操作
activeDetectionHistory.Enqueue(currentFrameSuccess);
while (activeDetectionHistory.Count > WINDOW_SIZE) 
    activeDetectionHistory.Dequeue(); // 🔴 频繁的内存操作

double successRate = (double)activeDetectionHistory.Count(s => s) / WINDOW_SIZE; // 🔴 LINQ分配

优化后的实现

// ✅ 高性能循环缓冲区
public struct CircularBuffer<T> where T : struct
{
    private readonly T[] _buffer;
    private int _head;
    private int _count;
    public readonly int Capacity;

    public CircularBuffer(int capacity)
    {
        _buffer = new T[capacity];
        _head = 0;
        _count = 0;
        Capacity = capacity;
    }

    public void Add(T item)
    {
        _buffer[(_head + _count) % _buffer.Length] = item;
        if (_count < _buffer.Length) 
            _count++;
        else 
            _head = (_head + 1) % _buffer.Length;
    }

    public int Count => _count;
    public bool IsFull => _count == _buffer.Length;

    // 零分配的成功率计算
    public double CalculateBooleanSuccessRate()
    {
        if (_count == 0) return 0.0;
        
        int successCount = 0;
        for (int i = 0; i < _count; i++)
        {
            int index = (_head + i) % _buffer.Length;
            if (_buffer[index] is bool success && success)
                successCount++;
        }
        return (double)successCount / _count;
    }

    // 零分配的数值平均值计算
    public double CalculateAverage()
    {
        if (_count == 0) return 0.0;
        
        double sum = 0.0;
        for (int i = 0; i < _count; i++)
        {
            int index = (_head + i) % _buffer.Length;
            if (_buffer[index] is double value)
                sum += value;
        }
        return sum / _count;
    }
}

// 在制导系统中使用
public class MillimeterWaveGuidanceSystem : BaseGuidanceSystem
{
    // ✅ 使用循环缓冲区替代Queue
    private CircularBuffer<bool> _detectionHistory = new(TRACK_DETECTION_WINDOW_SIZE);
    private CircularBuffer<double> _snrHistory = new(LOCK_SNR_WINDOW_SIZE);

    private bool TryDetectTarget(/* 参数 */)
    {
        // ... 检测逻辑
        
        // ✅ 零分配的历史记录更新
        _detectionHistory.Add(currentFrameSuccess);
        
        // ✅ 零分配的成功率计算
        if (_detectionHistory.IsFull)
        {
            double successRate = _detectionHistory.CalculateBooleanSuccessRate();
            bool overallSuccess = successRate >= SUCCESS_RATE_THRESHOLD;
            return overallSuccess;
        }
        
        return currentFrameSuccess;
    }
}

性能对比测试

测试代码示例

[Benchmark]
public class SimulationPerformanceTest
{
    private SimulationManager _optimizedManager;
    private SimulationManager _originalManager;
    private List<SimulationElement> _testEntities;

    [GlobalSetup]
    public void Setup()
    {
        // 创建测试实体
        _testEntities = CreateTestEntities(1000);
        
        _optimizedManager = new SimulationManager(); // 使用优化版本
        _originalManager = new SimulationManager();  // 使用原始版本
        
        // 注册实体
        foreach (var entity in _testEntities)
        {
            _optimizedManager.RegisterEntity(entity.Id, entity);
            _originalManager.RegisterEntity(entity.Id, entity);
        }
    }

    [Benchmark(Baseline = true)]
    public void OriginalUpdateSimulation()
    {
        _originalManager.Update(0.016); // 60 FPS
    }

    [Benchmark]
    public void OptimizedUpdateSimulation()
    {
        _optimizedManager.Update(0.016); // 60 FPS
    }
}

// 预期结果:
// |              Method |      Mean |    Error |   StdDev | Ratio |   Gen 0 |   Gen 1 | Allocated |
// |-------------------- |----------:|---------:|---------:|------:|--------:|--------:|----------:|
// | OriginalSimulation  | 1.234 ms  | 0.024 ms | 0.021 ms |  1.00 | 150.391 |  75.195 |   2.1 MB  |
// | OptimizedSimulation | 0.456 ms  | 0.009 ms | 0.008 ms |  0.37 |   7.813 |   0.000 |  0.12 MB  |

实施检查清单

阶段1对象池实施

  • 创建SimulationObjectPools类
  • 实现ListPooledObjectPolicy
  • 修改SimulationManager.UpdateSimulation()
  • 修改SimulationManager.CheckHits()
  • 添加性能测试
  • 验证功能正确性

阶段2事件系统优化

  • 优化PublishEvent方法
  • 消除ToList()调用
  • 替换foreach为for循环
  • 添加类型化的事件处理器缓存
  • 测试事件发布性能

阶段3图像处理优化

  • 创建ImageProcessingPools
  • 实现池化的连通区域分析
  • 优化Blob创建和管理
  • 添加循环缓冲区支持
  • 性能基准测试

每个阶段完成后都应该运行完整的测试套件,确保功能正确性不受影响。