18 KiB
18 KiB
C# 威胁源库性能优化实施示例
示例1:SimulationManager对象池优化
原始代码问题
// 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创建和管理
- 添加循环缓冲区支持
- 性能基准测试
每个阶段完成后都应该运行完整的测试套件,确保功能正确性不受影响。