ThreatSourceLibaray/docs/project/csharp_performance_optimization_plan.md

502 lines
15 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# 威胁源仿真库性能优化方案
## 文档信息
- **创建日期**: 2024年12月
- **版本**: 1.0
- **目标**: 解决C#运行时GC停顿和性能瓶颈问题
## 项目性能现状分析
### 代码规模统计
- **C#源文件**: 75个
- **代码总行数**: 约23,621行
- **核心类数量**: 120+个
- **主要性能热点**: 10个关键模块
### 性能瓶颈识别
#### 🔴 高优先级问题(严重影响)
##### 1. SimulationManager内存分配风暴
**问题位置**: `ThreatSource/src/Simulation/SimulationManager.cs:145-191`
```csharp
// 当前问题代码
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`
```csharp
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`
```csharp
var handlers = actualHandlers.ToList(); // 防御性复制
var handlers = typeHandlers.ToList(); // 防御性复制
```
**性能影响**: 每次事件发布都创建处理器列表副本
#### 🟡 中优先级问题(中等影响)
##### 4. 制导系统历史队列管理
**问题位置**: 多个制导系统类
```csharp
private readonly Queue<bool> activeDetectionHistory = new();
private readonly Queue<double> lockSnrHistory = new();
// 频繁的Enqueue/Dequeue操作
```
##### 5. 字符串操作性能问题
**问题位置**: 多个ToString()方法
```csharp
// ElementStatusInfo.cs:57
string extendedInfo = string.Join(", ", ExtendedProperties.Select(p =>
$"{p.Key}={valueStr}"));
```
##### 6. 装箱拆箱问题
**问题位置**: `ThreatSource/src/Equipment/EquipmentProperties.cs:41`
```csharp
public object Value { get; set; } = 0.0; // 装箱问题
public Dictionary<string, ParameterValue> CustomParameters { get; set; }
```
## 详细优化方案
### 第一阶段内存管理优化预期性能提升40-60%
#### 方案1.1SimulationManager对象池化
```csharp
// 新增:对象池管理器
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:红外图像处理优化
```csharp
// 新增:图像处理对象池
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:事件系统零分配优化
```csharp
// 优化的事件发布方法
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:制导系统历史数据优化
```csharp
// 使用循环缓冲区替代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:字符串操作优化
```csharp
// 使用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:消除装箱拆箱
```csharp
// 泛型参数值类
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.1SIMD向量化计算
```csharp
// 向量化的距离计算
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:内存预分配策略
```csharp
// 仿真管理器预分配策略
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.1Debug输出优化
```csharp
// 条件编译和高性能日志
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:配置驱动的性能调优
```csharp
// 性能配置类
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+实体
## 风险评估和缓解措施
### 主要风险
1. **代码复杂度增加**: 对象池和内存管理增加复杂性
2. **调试困难**: 优化后的代码可能难以调试
3. **兼容性问题**: 优化可能引入subtle bugs
### 缓解措施
1. **渐进式实施**: 每阶段独立验证
2. **性能测试套件**: 建立全面的性能回归测试
3. **配置开关**: 允许动态启用/禁用优化
4. **详细文档**: 记录所有优化决策和实现细节
## 成功标准
### 性能基准
- 1000实体仿真场景下稳定运行60FPS
- GC停顿时间<10ms
- 内存使用<1GB
### 质量标准
- 所有现有测试通过
- 新增性能测试覆盖率>90%
- 代码质量保持或提升
---
**注意**: 本优化方案需要.NET 6+支持。如使用较早版本的.NET Framework某些优化技术需要调整或替换。
## 性能测试
```bash
dotnet test --configuration Release --filter "RunPerformanceTest" --verbosity detailed --logger "console;verbosity=detailed"
```