15 KiB
15 KiB
C# 威胁源仿真库性能优化方案
文档信息
- 创建日期: 2024年12月
- 版本: 1.0
- 目标: 解决C#运行时GC停顿和性能瓶颈问题
项目性能现状分析
代码规模统计
- C#源文件: 75个
- 代码总行数: 约23,621行
- 核心类数量: 120+个
- 主要性能热点: 10个关键模块
性能瓶颈识别
🔴 高优先级问题(严重影响)
1. SimulationManager内存分配风暴
问题位置: ThreatSource/src/Simulation/SimulationManager.cs:145-191
// 当前问题代码
List<SimulationElement> activeElements = entities.Values
.Cast<SimulationElement>()
.Where(e => e.IsActive)
.ToList();
var activeMissiles = entities.Values.OfType<BaseMissile>().Where(e => e.IsActive).ToList();
var activeTargets = entities.Values.OfType<Tank>().Where(e => e.IsActive).ToList();
性能影响: 每帧分配3个大型List,约300-1000个对象,触发Gen0/Gen1 GC
2. 红外图像处理大量临时对象
问题位置: ThreatSource/src/Guidance/InfraredTargetRecognizer.cs:159-228
List<Blob> blobs = new List<Blob>();
Queue<(int x, int y)> queue = new Queue<(int x, int y)>();
List<Blob> filteredBlobs = [];
性能影响: 每次图像处理分配数百个临时对象和像素列表
3. 事件系统频繁复制
问题位置: ThreatSource/src/Simulation/SimulationManager.cs:268-317
var handlers = actualHandlers.ToList(); // 防御性复制
var handlers = typeHandlers.ToList(); // 防御性复制
性能影响: 每次事件发布都创建处理器列表副本
🟡 中优先级问题(中等影响)
4. 制导系统历史队列管理
问题位置: 多个制导系统类
private readonly Queue<bool> activeDetectionHistory = new();
private readonly Queue<double> lockSnrHistory = new();
// 频繁的Enqueue/Dequeue操作
5. 字符串操作性能问题
问题位置: 多个ToString()方法
// ElementStatusInfo.cs:57
string extendedInfo = string.Join(", ", ExtendedProperties.Select(p =>
$"{p.Key}={valueStr}"));
6. 装箱拆箱问题
问题位置: ThreatSource/src/Equipment/EquipmentProperties.cs:41
public object Value { get; set; } = 0.0; // 装箱问题
public Dictionary<string, ParameterValue> CustomParameters { get; set; }
详细优化方案
第一阶段:内存管理优化(预期性能提升:40-60%)
方案1.1:SimulationManager对象池化
// 新增:对象池管理器
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()
{
_elementListPool = new ObjectPool<List<SimulationElement>>(
createFunc: () => new List<SimulationElement>(1000),
resetAction: list => list.Clear(),
maximumRetained: 4
);
// 其他池的初始化...
}
public List<SimulationElement> GetElementList() => _elementListPool.Get();
public void ReturnElementList(List<SimulationElement> list) => _elementListPool.Return(list);
}
// 优化后的UpdateSimulation方法
private void UpdateSimulation(double deltaTime)
{
var activeElements = _objectPools.GetElementList();
try
{
lock (_lock)
{
foreach (var entity in entities.Values)
{
if (entity is SimulationElement element && element.IsActive)
{
activeElements.Add(element);
}
}
}
// 使用预分配的列表更新实体
foreach (var element in activeElements)
{
try { element.Update(deltaTime); }
catch (Exception ex) { Debug.WriteLine($"更新实体 {element.Id} 时发生错误: {ex.Message}"); }
}
}
finally
{
_objectPools.ReturnElementList(activeElements);
}
}
方案1.2:红外图像处理优化
// 新增:图像处理对象池
public class ImageProcessingPools
{
private readonly ObjectPool<List<Blob>> _blobListPool;
private readonly ObjectPool<Queue<(int, int)>> _pixelQueuePool;
private readonly ObjectPool<List<(int, int)>> _pixelListPool;
// 池化的图像分割方法
public List<Blob> PerformConnectedComponentAnalysis(InfraredImage image)
{
var blobs = _blobListPool.Get();
var queue = _pixelQueuePool.Get();
var pixelList = _pixelListPool.Get();
try
{
// 重用现有分析逻辑,但使用池化对象
// ... 具体实现
return new List<Blob>(blobs); // 返回副本
}
finally
{
_blobListPool.Return(blobs);
_pixelQueuePool.Return(queue);
_pixelListPool.Return(pixelList);
}
}
}
方案1.3:事件系统零分配优化
// 优化的事件发布方法
public void PublishEvent<T>(T evt) where T : class
{
if (evt == null) throw new ArgumentNullException(nameof(evt));
var eventType = typeof(T);
// 直接遍历,避免ToList()
if (eventHandlers.TryGetValue(eventType, out var handlers))
{
// 使用for循环而不是foreach,避免枚举器分配
for (int i = 0; i < handlers.Count; i++)
{
try
{
((Action<T>)handlers[i]).Invoke(evt);
}
catch (Exception ex)
{
Debug.WriteLine($"[事件] 处理异常: {ex.Message}");
}
}
}
}
第二阶段:算法和数据结构优化(预期性能提升:20-30%)
方案2.1:制导系统历史数据优化
// 使用循环缓冲区替代Queue
public struct CircularBuffer<T>
{
private readonly T[] _buffer;
private int _head;
private int _count;
public CircularBuffer(int capacity)
{
_buffer = new T[capacity];
_head = 0;
_count = 0;
}
public void Add(T item)
{
_buffer[(_head + _count) % _buffer.Length] = item;
if (_count < _buffer.Length) _count++;
else _head = (_head + 1) % _buffer.Length;
}
public double CalculateSuccessRate() where T : struct, IConvertible
{
if (_count == 0) return 0.0;
int successCount = 0;
for (int i = 0; i < _count; i++)
{
if (_buffer[(_head + i) % _buffer.Length].ToBoolean(null))
successCount++;
}
return (double)successCount / _count;
}
}
// 在制导系统中使用
private CircularBuffer<bool> _detectionHistory = new(TRACK_DETECTION_WINDOW_SIZE);
private CircularBuffer<double> _snrHistory = new(LOCK_SNR_WINDOW_SIZE);
方案2.2:字符串操作优化
// 使用StringBuilder和字符串池
public static class StringBuilderPool
{
private static readonly ObjectPool<StringBuilder> _pool = new ObjectPool<StringBuilder>(
createFunc: () => new StringBuilder(512),
resetAction: sb => sb.Clear(),
maximumRetained: Environment.ProcessorCount * 2
);
public static StringBuilder Get() => _pool.Get();
public static void Return(StringBuilder sb) => _pool.Return(sb);
}
// 优化的ToString方法
public override string ToString()
{
var sb = StringBuilderPool.Get();
try
{
sb.Append('[').Append(ElementType).Append("] Id=").Append(Id);
sb.Append(", Active=").Append(IsActive);
sb.Append(", 位置=").Append(KState.Position);
// ... 其他属性
if (ExtendedProperties.Count > 0)
{
sb.Append(", ");
bool first = true;
foreach (var kvp in ExtendedProperties)
{
if (!first) sb.Append(", ");
sb.Append(kvp.Key).Append('=');
FormatValue(sb, kvp.Value);
first = false;
}
}
return sb.ToString();
}
finally
{
StringBuilderPool.Return(sb);
}
}
方案2.3:消除装箱拆箱
// 泛型参数值类
public readonly struct ParameterValue<T> where T : struct
{
public readonly T Value;
public readonly string Unit;
public readonly string Category;
public readonly string Description;
public ParameterValue(T value, string unit = "", string category = "", string description = "")
{
Value = value;
Unit = unit ?? "";
Category = category ?? "";
Description = description ?? "";
}
}
// 类型安全的参数字典
public class TypedParameterDictionary
{
private readonly Dictionary<string, ParameterValue<double>> _doubleParams = new();
private readonly Dictionary<string, ParameterValue<int>> _intParams = new();
private readonly Dictionary<string, ParameterValue<bool>> _boolParams = new();
private readonly Dictionary<string, string> _stringParams = new();
public void SetDouble(string key, double value, string unit = "", string category = "")
{
_doubleParams[key] = new ParameterValue<double>(value, unit, category);
}
public T GetValue<T>(string key, T defaultValue = default) where T : struct
{
if (typeof(T) == typeof(double) && _doubleParams.TryGetValue(key, out var doubleParam))
return (T)(object)doubleParam.Value;
// 其他类型的处理...
return defaultValue;
}
}
第三阶段:高级优化技术(预期性能提升:10-20%)
方案3.1:SIMD向量化计算
// 向量化的距离计算
public static void CalculateDistancesBatch(ReadOnlySpan<Vector3D> positions1,
ReadOnlySpan<Vector3D> positions2,
Span<double> results)
{
Debug.Assert(positions1.Length == positions2.Length);
Debug.Assert(results.Length >= positions1.Length);
for (int i = 0; i < positions1.Length; i++)
{
var delta = positions1[i] - positions2[i];
results[i] = delta.Magnitude();
}
}
// 向量化的RCS计算
public static void CalculateRcsBatch(ReadOnlySpan<double> distances,
ReadOnlySpan<double> rcsValues,
ReadOnlySpan<double> transmittances,
Span<double> snrResults)
{
// 使用System.Numerics.Vector进行SIMD优化
// ... 具体实现
}
方案3.2:内存预分配策略
// 仿真管理器预分配策略
public class PreallocatedSimulationManager
{
// 预分配常用大小的数组
private readonly double[] _tempDistances = new double[1000];
private readonly Vector3D[] _tempPositions = new Vector3D[1000];
private readonly bool[] _tempResults = new bool[1000];
// 使用ArrayPool for大型临时数组
private static readonly ArrayPool<double> _doubleArrayPool = ArrayPool<double>.Shared;
private static readonly ArrayPool<Vector3D> _vectorArrayPool = ArrayPool<Vector3D>.Create();
public void ProcessBatchOperations(int count)
{
double[] distances = count <= 1000 ? _tempDistances : _doubleArrayPool.Rent(count);
try
{
// 批量处理操作
}
finally
{
if (distances != _tempDistances)
_doubleArrayPool.Return(distances);
}
}
}
第四阶段:专项优化
方案4.1:Debug输出优化
// 条件编译和高性能日志
public static class PerformanceLogger
{
[Conditional("DEBUG")]
public static void LogDebug(string message)
{
Debug.WriteLine(message);
}
// 格式化字符串的延迟计算
[Conditional("DEBUG")]
public static void LogDebugFormat<T1, T2>(string format, T1 arg1, T2 arg2)
{
Debug.WriteLine(format, arg1, arg2);
}
// 使用插值字符串处理程序(.NET 6+)
[Conditional("DEBUG")]
public static void LogDebugInterpolated([InterpolatedStringHandler] ref LogInterpolatedStringHandler handler)
{
Debug.WriteLine(handler.ToString());
}
}
方案4.2:配置驱动的性能调优
// 性能配置类
public class PerformanceConfig
{
public bool EnableObjectPooling { get; set; } = true;
public bool EnableStringPooling { get; set; } = true;
public bool EnableBatchProcessing { get; set; } = true;
public int ObjectPoolMaxSize { get; set; } = 1000;
public int StringBuilderPoolSize { get; set; } = 100;
public bool EnableSIMD { get; set; } = true;
public bool EnableDebugLogging { get; set; } = false;
}
实施计划和时间估算
阶段1:基础内存优化(2-3周)
- 周1: SimulationManager对象池化
- 周2: 红外图像处理优化
- 周3: 事件系统优化和测试
阶段2:算法优化(2-3周)
- 周4: 制导系统历史数据优化
- 周5: 字符串操作和装箱优化
- 周6: 集成测试和性能验证
阶段3:高级优化(1-2周)
- 周7: SIMD优化和内存预分配
- 周8: 全面性能测试和调优
阶段4:验证和部署(1周)
- 周9: 性能基准测试、文档更新
预期性能提升
GC性能改善
- Gen0 GC频率: 减少60-80%
- Gen1 GC频率: 减少40-60%
- GC停顿时间: 减少50-70%
整体性能提升
- 仿真步进性能: 提升40-60%
- 内存使用: 减少30-50%
- CPU占用: 减少20-40%
具体指标预期
- 每帧内存分配: 从~10MB降至~2MB
- 仿真FPS: 从30-50提升至60-100
- 大规模场景支持: 从100实体提升至500+实体
风险评估和缓解措施
主要风险
- 代码复杂度增加: 对象池和内存管理增加复杂性
- 调试困难: 优化后的代码可能难以调试
- 兼容性问题: 优化可能引入subtle bugs
缓解措施
- 渐进式实施: 每阶段独立验证
- 性能测试套件: 建立全面的性能回归测试
- 配置开关: 允许动态启用/禁用优化
- 详细文档: 记录所有优化决策和实现细节
成功标准
性能基准
- 1000实体仿真场景下稳定运行60FPS
- GC停顿时间<10ms
- 内存使用<1GB
质量标准
- 所有现有测试通过
- 新增性能测试覆盖率>90%
- 代码质量保持或提升
注意: 本优化方案需要.NET 6+支持。如使用较早版本的.NET Framework,某些优化技术需要调整或替换。
性能测试
dotnet test --configuration Release --filter "RunPerformanceTest" --verbosity detailed --logger "console;verbosity=detailed"