ThreatSourceLibaray/docs/project/performance_optimization_examples.md

596 lines
18 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.

# C# 威胁源库性能优化实施示例
## 示例1SimulationManager对象池优化
### 原始代码问题
```csharp
// 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创建对象池基础设施
```csharp
// 新文件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
```csharp
// 修改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事件系统零分配优化
### 原始代码问题
```csharp
// 当前的事件发布实现
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造成装箱
}
}
}
```
### 优化后的实现
```csharp
// ✅ 零分配的事件发布
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红外图像处理优化
### 原始代码问题
```csharp
// 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;
}
```
### 优化后的实现
```csharp
// 新增:图像处理对象池
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制导系统历史数据优化
### 原始代码问题
```csharp
// 多个制导系统中的问题
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分配
```
### 优化后的实现
```csharp
// ✅ 高性能循环缓冲区
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;
}
}
```
## 性能对比测试
### 测试代码示例
```csharp
[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<T>
- [ ] 修改SimulationManager.UpdateSimulation()
- [ ] 修改SimulationManager.CheckHits()
- [ ] 添加性能测试
- [ ] 验证功能正确性
### 阶段2事件系统优化
- [ ] 优化PublishEvent方法
- [ ] 消除ToList()调用
- [ ] 替换foreach为for循环
- [ ] 添加类型化的事件处理器缓存
- [ ] 测试事件发布性能
### 阶段3图像处理优化
- [ ] 创建ImageProcessingPools
- [ ] 实现池化的连通区域分析
- [ ] 优化Blob创建和管理
- [ ] 添加循环缓冲区支持
- [ ] 性能基准测试
每个阶段完成后都应该运行完整的测试套件,确保功能正确性不受影响。