优化了毫米波制导的性能,修改了红外成像制导的参数,包括复合制导
This commit is contained in:
parent
dea12867f0
commit
131ba3997c
@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RunSettings>
|
||||
<TestRunParameters>
|
||||
<Parameter name="SkipPerformanceTests" value="true" />
|
||||
</TestRunParameters>
|
||||
<RunConfiguration>
|
||||
<TestSessionTimeout>120000</TestSessionTimeout>
|
||||
</RunConfiguration>
|
||||
</RunSettings>
|
||||
@ -1,147 +0,0 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Diagnostics;
|
||||
using ThreatSource.Utils; // Assuming Vector3D is here, adjust if necessary
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
namespace ThreatSource.Tests.Utils
|
||||
{
|
||||
[TestClass]
|
||||
public class Vector3DPerformanceTests
|
||||
{
|
||||
private const int Iterations = 1000000; // Number of iterations for performance testing
|
||||
|
||||
private Vector3D CreateVector(double i)
|
||||
{
|
||||
// Helper to create slightly different vectors
|
||||
return new Vector3D(i, i + 1.5, i * 0.8);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Baseline_Vector3D_Class_Performance()
|
||||
{
|
||||
// This test assumes Vector3D is currently a CLASS.
|
||||
// We will run this once, record results, then change Vector3D to struct and run again.
|
||||
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
List<Vector3D> vectors = new List<Vector3D>(Iterations);
|
||||
double totalMagnitude = 0;
|
||||
Random rand = new Random(123); // Seeded for reproducibility
|
||||
|
||||
// --- Test 1: Creation Performance ---
|
||||
stopwatch.Start();
|
||||
for (int i = 0; i < Iterations; i++)
|
||||
{
|
||||
vectors.Add(CreateVector(i * rand.NextDouble()));
|
||||
}
|
||||
stopwatch.Stop();
|
||||
Console.WriteLine($"[Baseline Class] Creation of {Iterations} Vector3D instances: {stopwatch.ElapsedMilliseconds} ms");
|
||||
long creationTime = stopwatch.ElapsedMilliseconds;
|
||||
|
||||
// Ensure vectors are used to prevent over-optimization by compiler
|
||||
if (vectors.Count == 0) throw new Exception("Vector list empty after creation.");
|
||||
|
||||
Vector3D tempVector1 = CreateVector(10.1);
|
||||
Vector3D tempVector2 = CreateVector(20.2);
|
||||
|
||||
// --- Test 2: Addition Performance ---
|
||||
stopwatch.Restart();
|
||||
for (int i = 0; i < Iterations; i++)
|
||||
{
|
||||
tempVector1 = tempVector1 + vectors[i];
|
||||
}
|
||||
stopwatch.Stop();
|
||||
Console.WriteLine($"[Baseline Class] {Iterations} Vector3D Additions: {stopwatch.ElapsedMilliseconds} ms");
|
||||
long additionTime = stopwatch.ElapsedMilliseconds;
|
||||
|
||||
// --- Test 3: Subtraction Performance ---
|
||||
stopwatch.Restart();
|
||||
for (int i = 0; i < Iterations; i++)
|
||||
{
|
||||
tempVector1 = tempVector1 - vectors[i];
|
||||
}
|
||||
stopwatch.Stop();
|
||||
Console.WriteLine($"[Baseline Class] {Iterations} Vector3D Subtractions: {stopwatch.ElapsedMilliseconds} ms");
|
||||
long subtractionTime = stopwatch.ElapsedMilliseconds;
|
||||
|
||||
// --- Test 4: Scalar Multiplication Performance ---
|
||||
stopwatch.Restart();
|
||||
for (int i = 0; i < Iterations; i++)
|
||||
{
|
||||
tempVector1 = vectors[i] * 2.5;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
Console.WriteLine($"[Baseline Class] {Iterations} Vector3D Scalar Multiplications: {stopwatch.ElapsedMilliseconds} ms");
|
||||
long scalarMultTime = stopwatch.ElapsedMilliseconds;
|
||||
|
||||
// --- Test 5: Dot Product Performance ---
|
||||
double dotProductSum = 0;
|
||||
stopwatch.Restart();
|
||||
for (int i = 0; i < Iterations; i++)
|
||||
{
|
||||
dotProductSum += Vector3D.DotProduct(vectors[i], tempVector2);
|
||||
}
|
||||
stopwatch.Stop();
|
||||
Console.WriteLine($"[Baseline Class] {Iterations} Vector3D Dot Products: {stopwatch.ElapsedMilliseconds} ms");
|
||||
long dotProductTime = stopwatch.ElapsedMilliseconds;
|
||||
|
||||
// --- Test 6: Cross Product Performance ---
|
||||
stopwatch.Restart();
|
||||
for (int i = 0; i < Iterations; i++)
|
||||
{
|
||||
tempVector1 = Vector3D.CrossProduct(vectors[i], tempVector2);
|
||||
}
|
||||
stopwatch.Stop();
|
||||
Console.WriteLine($"[Baseline Class] {Iterations} Vector3D Cross Products: {stopwatch.ElapsedMilliseconds} ms");
|
||||
long crossProductTime = stopwatch.ElapsedMilliseconds;
|
||||
|
||||
// --- Test 7: Magnitude Performance ---
|
||||
stopwatch.Restart();
|
||||
for (int i = 0; i < Iterations; i++)
|
||||
{
|
||||
totalMagnitude += vectors[i].Magnitude();
|
||||
}
|
||||
stopwatch.Stop();
|
||||
Console.WriteLine($"[Baseline Class] {Iterations} Vector3D Magnitudes: {stopwatch.ElapsedMilliseconds} ms");
|
||||
long magnitudeTime = stopwatch.ElapsedMilliseconds;
|
||||
|
||||
// --- Test 8: Normalization Performance ---
|
||||
stopwatch.Restart();
|
||||
for (int i = 0; i < Iterations; i++)
|
||||
{
|
||||
// Avoid normalizing zero vectors which might throw exceptions or return NaN
|
||||
if (vectors[i].MagnitudeSquared() > 0.00001)
|
||||
{
|
||||
tempVector1 = vectors[i].Normalize();
|
||||
}
|
||||
else
|
||||
{
|
||||
tempVector1 = vectors[i]; // Assign to ensure work is done
|
||||
}
|
||||
}
|
||||
stopwatch.Stop();
|
||||
Console.WriteLine($"[Baseline Class] {Iterations} Vector3D Normalizations: {stopwatch.ElapsedMilliseconds} ms");
|
||||
long normalizeTime = stopwatch.ElapsedMilliseconds;
|
||||
|
||||
Console.WriteLine($"[Baseline Class] Total magnitude sum (to prevent optimization): {totalMagnitude}");
|
||||
Console.WriteLine($"[Baseline Class] Final tempVector1 (to prevent optimization): {tempVector1}");
|
||||
Console.WriteLine($"[Baseline Class] Final dotProductSum (to prevent optimization): {dotProductSum}");
|
||||
|
||||
// For MSTest, Assert.Inconclusive can be used to output results without failing the test.
|
||||
// Alternatively, a simple Console.WriteLine at the end of the test with a summary is also fine
|
||||
// if the test isn't meant to pass/fail based on performance but just to gather data.
|
||||
// For this baseline, we'll use Assert.Inconclusive to clearly mark the output in test results.
|
||||
string resultSummary = $"Baseline performance (Vector3D as CLASS):\n" +
|
||||
$"Creation: {creationTime} ms\n" +
|
||||
$"Addition: {additionTime} ms\n" +
|
||||
$"Subtraction: {subtractionTime} ms\n" +
|
||||
$"Scalar Mult: {scalarMultTime} ms\n" +
|
||||
$"Dot Product: {dotProductTime} ms\n" +
|
||||
$"Cross Product: {crossProductTime} ms\n" +
|
||||
$"Magnitude: {magnitudeTime} ms\n" +
|
||||
$"Normalization: {normalizeTime} ms";
|
||||
Console.WriteLine(resultSummary); // Ensure it's also printed to console output for easy viewing
|
||||
Assert.Inconclusive(resultSummary); // Marks test as inconclusive and shows message in test explorer
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -83,8 +83,8 @@ JammingResistanceThreshold = 1.0e-5 # 干扰抗性阈值 (瓦特)
|
||||
MaxDetectionRange = 1000.0 # 最大探测距离 (米)
|
||||
SearchFieldOfView = 12.0 # 搜索视场角 (度)
|
||||
TrackFieldOfView = 6.0 # 跟踪视场角 (度)
|
||||
ImageWidth = 640 # 图像宽度 (像素)
|
||||
ImageHeight = 480 # 图像高度 (像素)
|
||||
ImageWidth = 256 # 图像宽度 (像素)
|
||||
ImageHeight = 256 # 图像高度 (像素)
|
||||
BackgroundIntensity = 1.0e-4 # 背景辐射强度 (瓦特/球面度)
|
||||
SearchRecognitionProbability = 0.6 # 搜索模式目标识别概率阈值
|
||||
TrackRecognitionProbability = 0.8 # 跟踪模式目标识别概率阈值
|
||||
|
||||
@ -77,8 +77,8 @@ CodeValue = 1010 # 激光编码的实际值
|
||||
MaxDetectionRange = 1000.0 # 最大探测距离 (米)
|
||||
SearchFieldOfView = 12.0 # 搜索视场角 (度)
|
||||
TrackFieldOfView = 6.0 # 跟踪视场角 (度)
|
||||
ImageWidth = 640 # 图像宽度 (像素)
|
||||
ImageHeight = 480 # 图像高度 (像素)
|
||||
ImageWidth = 256 # 图像宽度 (像素)
|
||||
ImageHeight = 256 # 图像高度 (像素)
|
||||
BackgroundIntensity = 1.0e-4 # 背景辐射强度 (瓦特/球面度)
|
||||
SearchRecognitionProbability = 0.6 # 搜索模式目标识别概率阈值
|
||||
TrackRecognitionProbability = 0.8 # 跟踪模式目标识别概率阈值
|
||||
|
||||
@ -166,8 +166,6 @@ namespace ThreatSource.Guidance
|
||||
|
||||
// 更新导引头朝向
|
||||
KState.Orientation = targetOrientation;
|
||||
|
||||
Debug.WriteLine($"[INFRARED_COMMAND] 导引头朝向已调整指向目标: {targetOrientation}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -409,8 +409,6 @@ namespace ThreatSource.Guidance
|
||||
|
||||
// 更新导引头朝向
|
||||
KState.Orientation = targetOrientation;
|
||||
|
||||
Debug.WriteLine($"[IR IMAGING] 导引头朝向已调整指向目标 {currentlyTrackedTargetId}: {targetOrientation}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -690,8 +690,6 @@ namespace ThreatSource.Guidance
|
||||
|
||||
// 更新导引头朝向
|
||||
KState.Orientation = targetOrientation;
|
||||
|
||||
Debug.WriteLine($"[LASER_SEMI_ACTIVE] 导引头朝向已调整指向目标: {targetOrientation}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -91,14 +91,14 @@ namespace ThreatSource.Guidance
|
||||
private string? currentlyTrackedTargetId;
|
||||
|
||||
/// <summary>
|
||||
/// 当前活动模式 (Search焦点、Track、Lock) 的探测历史队列
|
||||
/// 当前活动模式 (Search焦点、Track、Lock) 的探测历史缓冲区
|
||||
/// </summary>
|
||||
private readonly Queue<bool> activeDetectionHistory = new();
|
||||
private CircularBuffer<bool> activeDetectionHistory = new(TRACK_DETECTION_WINDOW_SIZE);
|
||||
|
||||
/// <summary>
|
||||
/// Lock模式的SNR历史队列,用于计算平均SNR
|
||||
/// Lock模式的SNR历史缓冲区,用于计算平均SNR
|
||||
/// </summary>
|
||||
private readonly Queue<double> lockSnrHistory = new();
|
||||
private CircularBuffer<double> lockSnrHistory = new(LOCK_SNR_WINDOW_SIZE);
|
||||
|
||||
/// <summary>
|
||||
/// Track模式探测历史滑动窗口大小
|
||||
@ -273,8 +273,6 @@ namespace ThreatSource.Guidance
|
||||
|
||||
// 更新导引头朝向
|
||||
KState.Orientation = targetOrientation;
|
||||
|
||||
Debug.WriteLine($"[MMW_GUIDANCE] 导引头朝向已调整指向目标 {currentlyTrackedTargetId}: {targetOrientation}");
|
||||
}
|
||||
}
|
||||
|
||||
@ -489,7 +487,7 @@ namespace ThreatSource.Guidance
|
||||
return double.MinValue; // 无历史数据
|
||||
}
|
||||
|
||||
double averageSnr = lockSnrHistory.Average();
|
||||
double averageSnr = lockSnrHistory.CalculateAverage();
|
||||
Debug.WriteLine($"[SNR平均] 窗口大小: {lockSnrHistory.Count}/{LOCK_SNR_WINDOW_SIZE}, 平均SNR: {averageSnr:F2}dB");
|
||||
return averageSnr;
|
||||
}
|
||||
@ -590,7 +588,7 @@ namespace ThreatSource.Guidance
|
||||
if (IsBlockingJammed)
|
||||
{
|
||||
if (currentMode != WorkMode.Search) SwitchToSearchMode();
|
||||
this.HasTarget = false;
|
||||
HasTarget = false;
|
||||
GuidanceAcceleration = Vector3D.Zero;
|
||||
HasGuidance = false;
|
||||
return;
|
||||
@ -629,8 +627,6 @@ namespace ThreatSource.Guidance
|
||||
{
|
||||
UpdateSeekerOrientation();
|
||||
}
|
||||
|
||||
Debug.WriteLine($"制导加速度: {GuidanceAcceleration}");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -731,7 +727,7 @@ namespace ThreatSource.Guidance
|
||||
case WorkMode.Search:
|
||||
if (IsTargetInBeam(missileVelocity, toTarget) && localSnrDb >= config.RecognitionSNRThreshold)
|
||||
{
|
||||
Debug.WriteLine($"[MMW SEARCH] TryDetect发现目标: {target.Id}, SNR: {localSnrDb:F2} dB.");
|
||||
Debug.WriteLine($"[MMW SEARCH] 发现目标: {target.Id}, SNR: {localSnrDb:F2} dB.");
|
||||
targetPosition = target.KState!.Position;
|
||||
UpdateStateAndPotentiallySwitchMode(true, localSnrDb, target.Id, targetPosition, deltaTime);
|
||||
return true;
|
||||
@ -745,23 +741,22 @@ namespace ThreatSource.Guidance
|
||||
}
|
||||
|
||||
bool currentFrameSuccessForTrack = IsTargetInBeam(missileVelocity, toTarget) && localSnrDb >= config.RecognitionSNRThreshold;
|
||||
activeDetectionHistory.Enqueue(currentFrameSuccessForTrack);
|
||||
while (activeDetectionHistory.Count > TRACK_DETECTION_WINDOW_SIZE) activeDetectionHistory.Dequeue();
|
||||
activeDetectionHistory.Add(currentFrameSuccessForTrack);
|
||||
|
||||
Debug.WriteLine($"[MMW TRACK] TryDetect目标 {currentlyTrackedTargetId} 本帧探测: {currentFrameSuccessForTrack}, SNR: {localSnrDb:F2} dB. 窗口 ({activeDetectionHistory.Count}/{TRACK_DETECTION_WINDOW_SIZE})");
|
||||
Debug.WriteLine($"[MMW TRACK] 目标 {currentlyTrackedTargetId} 本帧探测: {currentFrameSuccessForTrack}, SNR: {localSnrDb:F2} dB. 窗口 ({activeDetectionHistory.Count}/{TRACK_DETECTION_WINDOW_SIZE})");
|
||||
|
||||
bool trackOverallSuccess;
|
||||
if (activeDetectionHistory.Count == TRACK_DETECTION_WINDOW_SIZE)
|
||||
{
|
||||
double successRate = (double)activeDetectionHistory.Count(s => s) / TRACK_DETECTION_WINDOW_SIZE;
|
||||
double successRate = activeDetectionHistory.CalculateBooleanSuccessRate();
|
||||
trackOverallSuccess = successRate >= SUCCESS_RATE_THRESHOLD;
|
||||
if(trackOverallSuccess) Debug.WriteLine($"[MMW TRACK] TryDetect目标 {currentlyTrackedTargetId} 滑动窗口稳定 (率: {successRate:P2}).");
|
||||
else Debug.WriteLine($"[MMW TRACK] TryDetect目标 {currentlyTrackedTargetId} 滑动窗口不稳定 (率: {successRate:P2}).");
|
||||
if(trackOverallSuccess) Debug.WriteLine($"[MMW TRACK] 目标 {currentlyTrackedTargetId} 滑动窗口稳定 (成功率: {successRate:P2}).");
|
||||
else Debug.WriteLine($"[MMW TRACK] 目标 {currentlyTrackedTargetId} 滑动窗口不稳定 (成功率: {successRate:P2}).");
|
||||
}
|
||||
else
|
||||
{
|
||||
trackOverallSuccess = currentFrameSuccessForTrack;
|
||||
Debug.WriteLine($"[MMW TRACK] TryDetect目标 {currentlyTrackedTargetId} 窗口未满. trackOverallSuccess = currentFrameSuccessForTrack ({currentFrameSuccessForTrack}).");
|
||||
Debug.WriteLine($"[MMW TRACK] 目标 {currentlyTrackedTargetId} 窗口未满. 当前帧成功: {currentFrameSuccessForTrack}.");
|
||||
}
|
||||
|
||||
targetPosition = trackOverallSuccess ?
|
||||
@ -776,9 +771,8 @@ namespace ThreatSource.Guidance
|
||||
continue;
|
||||
}
|
||||
|
||||
// 添加SNR到历史队列
|
||||
lockSnrHistory.Enqueue(localSnrDb);
|
||||
while (lockSnrHistory.Count > LOCK_SNR_WINDOW_SIZE) lockSnrHistory.Dequeue();
|
||||
// 添加SNR到历史缓冲区
|
||||
lockSnrHistory.Add(localSnrDb);
|
||||
|
||||
// 计算平均SNR
|
||||
double averageSnr = CalculateAverageLockSnr();
|
||||
@ -787,23 +781,22 @@ namespace ThreatSource.Guidance
|
||||
double snrForDecision = lockSnrHistory.Count >= LOCK_SNR_WINDOW_SIZE ? averageSnr : localSnrDb;
|
||||
bool currentFrameSuccessForLock = IsTargetInBeam(missileVelocity, toTarget) && snrForDecision >= config.LockSNRThreshold;
|
||||
|
||||
activeDetectionHistory.Enqueue(currentFrameSuccessForLock);
|
||||
while (activeDetectionHistory.Count > TRACK_DETECTION_WINDOW_SIZE) activeDetectionHistory.Dequeue();
|
||||
activeDetectionHistory.Add(currentFrameSuccessForLock);
|
||||
|
||||
Debug.WriteLine($"[MMW LOCK] TryDetect目标 {currentlyTrackedTargetId} 本帧探测: {currentFrameSuccessForLock}, 瞬时SNR: {localSnrDb:F2}dB, 平均SNR: {averageSnr:F2}dB, 决策SNR: {snrForDecision:F2}dB. 窗口 ({activeDetectionHistory.Count}/{TRACK_DETECTION_WINDOW_SIZE}).");
|
||||
Debug.WriteLine($"[MMW LOCK] 目标 {currentlyTrackedTargetId} 本帧探测: {currentFrameSuccessForLock}, 瞬时SNR: {localSnrDb:F2}dB, 平均SNR: {averageSnr:F2}dB, 决策SNR: {snrForDecision:F2}dB. 窗口 ({activeDetectionHistory.Count}/{TRACK_DETECTION_WINDOW_SIZE}).");
|
||||
|
||||
bool lockOverallSuccess;
|
||||
if (activeDetectionHistory.Count == TRACK_DETECTION_WINDOW_SIZE)
|
||||
{
|
||||
double successRate = (double)activeDetectionHistory.Count(s => s) / TRACK_DETECTION_WINDOW_SIZE;
|
||||
double successRate = activeDetectionHistory.CalculateBooleanSuccessRate();
|
||||
lockOverallSuccess = successRate >= SUCCESS_RATE_THRESHOLD;
|
||||
if(lockOverallSuccess) Debug.WriteLine($"[MMW LOCK] TryDetect目标 {currentlyTrackedTargetId} 滑动窗口稳定 (率: {successRate:P2}).");
|
||||
else Debug.WriteLine($"[MMW LOCK] TryDetect目标 {currentlyTrackedTargetId} 滑动窗口不稳定 (率: {successRate:P2}).");
|
||||
if(lockOverallSuccess) Debug.WriteLine($"[MMW LOCK] 目标 {currentlyTrackedTargetId} 滑动窗口稳定 (成功率: {successRate:P2}).");
|
||||
else Debug.WriteLine($"[MMW LOCK] 目标 {currentlyTrackedTargetId} 滑动窗口不稳定 (成功率: {successRate:P2}).");
|
||||
}
|
||||
else
|
||||
{
|
||||
lockOverallSuccess = currentFrameSuccessForLock;
|
||||
Debug.WriteLine($"[MMW LOCK] TryDetect目标 {currentlyTrackedTargetId} 窗口未满. lockOverallSuccess = currentFrameSuccessForLock ({currentFrameSuccessForLock}).");
|
||||
Debug.WriteLine($"[MMW LOCK] 目标 {currentlyTrackedTargetId} 窗口未满. 当前帧成功: {currentFrameSuccessForLock}.");
|
||||
}
|
||||
|
||||
targetPosition = lockOverallSuccess ?
|
||||
@ -813,16 +806,6 @@ namespace ThreatSource.Guidance
|
||||
return lockOverallSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索模式:如果没有找到合适的目标,这是正常情况
|
||||
if (currentMode == WorkMode.Search)
|
||||
{
|
||||
Debug.WriteLine($"[MMW SEARCH] 本帧扫描完成,未发现符合条件的目标。螺旋参数: {spiralRadius * 180/Math.PI:F2}°/{MaxScanRadius * 180/Math.PI:F1}°");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine($"[MMW {currentMode.ToString().ToUpper()}] TryDetect循环结束,当前跟踪目标: {currentlyTrackedTargetId}");
|
||||
}
|
||||
|
||||
UpdateStateAndPotentiallySwitchMode(false, double.MinValue, currentlyTrackedTargetId, Vector3D.Zero, deltaTime);
|
||||
targetPosition = Vector3D.Zero;
|
||||
@ -842,7 +825,7 @@ namespace ThreatSource.Guidance
|
||||
{
|
||||
if (currentMode == WorkMode.Track || currentMode == WorkMode.Lock)
|
||||
{
|
||||
Debug.WriteLine($"[MMW {currentMode.ToString().ToUpper()}] UpdateState判定目标丢失/不稳定 (frameSuccess=false),切换到搜索模式。");
|
||||
Debug.WriteLine($"[MMW {currentMode.ToString().ToUpper()}] 判定目标丢失/不稳定 (frameSuccess=false),切换到搜索模式。");
|
||||
SwitchToSearchMode();
|
||||
}
|
||||
return;
|
||||
|
||||
195
ThreatSource/src/Utils/CircularBuffer.cs
Normal file
195
ThreatSource/src/Utils/CircularBuffer.cs
Normal file
@ -0,0 +1,195 @@
|
||||
using System;
|
||||
|
||||
namespace ThreatSource.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// 高性能循环缓冲区,用于替代Queue避免内存分配
|
||||
/// </summary>
|
||||
/// <typeparam name="T">缓冲区元素类型</typeparam>
|
||||
/// <remarks>
|
||||
/// 该类提供以下特性:
|
||||
/// - 零内存分配的添加和访问操作
|
||||
/// - 固定大小的预分配数组
|
||||
/// - O(1)复杂度的添加操作
|
||||
/// - 缓存友好的连续内存访问
|
||||
/// - 支持历史数据滑动窗口管理
|
||||
/// </remarks>
|
||||
public struct CircularBuffer<T> where T : struct
|
||||
{
|
||||
/// <summary>
|
||||
/// 内部存储数组
|
||||
/// </summary>
|
||||
private readonly T[] _buffer;
|
||||
|
||||
/// <summary>
|
||||
/// 头部索引(最旧元素位置)
|
||||
/// </summary>
|
||||
private int _head;
|
||||
|
||||
/// <summary>
|
||||
/// 当前元素数量
|
||||
/// </summary>
|
||||
private int _count;
|
||||
|
||||
/// <summary>
|
||||
/// 缓冲区容量
|
||||
/// </summary>
|
||||
public readonly int Capacity;
|
||||
|
||||
/// <summary>
|
||||
/// 当前元素数量
|
||||
/// </summary>
|
||||
public readonly int Count => _count;
|
||||
|
||||
/// <summary>
|
||||
/// 缓冲区是否已满
|
||||
/// </summary>
|
||||
public readonly bool IsFull => _count == _buffer.Length;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化指定容量的循环缓冲区
|
||||
/// </summary>
|
||||
/// <param name="capacity">缓冲区容量</param>
|
||||
public CircularBuffer(int capacity)
|
||||
{
|
||||
if (capacity <= 0)
|
||||
throw new ArgumentException("容量必须大于0", nameof(capacity));
|
||||
|
||||
_buffer = new T[capacity];
|
||||
_head = 0;
|
||||
_count = 0;
|
||||
Capacity = capacity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加新元素到缓冲区
|
||||
/// </summary>
|
||||
/// <param name="item">要添加的元素</param>
|
||||
/// <remarks>
|
||||
/// 如果缓冲区已满,将覆盖最旧的元素
|
||||
/// 操作复杂度:O(1)
|
||||
/// </remarks>
|
||||
public void Add(T item)
|
||||
{
|
||||
int writeIndex = (_head + _count) % _buffer.Length;
|
||||
_buffer[writeIndex] = item;
|
||||
|
||||
if (_count < _buffer.Length)
|
||||
{
|
||||
_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 缓冲区已满,移动头部指针覆盖最旧元素
|
||||
_head = (_head + 1) % _buffer.Length;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空缓冲区
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
_head = 0;
|
||||
_count = 0;
|
||||
// 不需要清零数组内容,因为会被新数据覆盖
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算布尔类型的成功率(专用于探测历史)
|
||||
/// </summary>
|
||||
/// <returns>成功率(0.0到1.0之间)</returns>
|
||||
/// <remarks>
|
||||
/// 仅当T为bool类型时使用
|
||||
/// 零分配的高性能实现
|
||||
/// </remarks>
|
||||
public readonly 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算数值的平均值(专用于SNR历史)
|
||||
/// </summary>
|
||||
/// <returns>平均值</returns>
|
||||
/// <remarks>
|
||||
/// 仅当T为数值类型时使用
|
||||
/// 零分配的高性能实现
|
||||
/// </remarks>
|
||||
public readonly double CalculateAverage()
|
||||
{
|
||||
if (_count == 0) return double.MinValue;
|
||||
|
||||
double sum = 0.0;
|
||||
for (int i = 0; i < _count; i++)
|
||||
{
|
||||
int index = (_head + i) % _buffer.Length;
|
||||
// 使用模式匹配处理不同数值类型
|
||||
sum += _buffer[index] switch
|
||||
{
|
||||
double d => d,
|
||||
float f => f,
|
||||
int n => n,
|
||||
long l => l,
|
||||
_ => 0.0
|
||||
};
|
||||
}
|
||||
return sum / _count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定索引的元素
|
||||
/// </summary>
|
||||
/// <param name="index">元素索引(0表示最旧元素)</param>
|
||||
/// <returns>指定位置的元素</returns>
|
||||
/// <exception cref="ArgumentOutOfRangeException">索引超出范围</exception>
|
||||
public readonly T this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < 0 || index >= _count)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
|
||||
int actualIndex = (_head + index) % _buffer.Length;
|
||||
return _buffer[actualIndex];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最新添加的元素
|
||||
/// </summary>
|
||||
/// <returns>最新元素</returns>
|
||||
/// <exception cref="InvalidOperationException">缓冲区为空</exception>
|
||||
public readonly T GetLatest()
|
||||
{
|
||||
if (_count == 0)
|
||||
throw new InvalidOperationException("缓冲区为空");
|
||||
|
||||
int latestIndex = (_head + _count - 1) % _buffer.Length;
|
||||
return _buffer[latestIndex];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最旧的元素
|
||||
/// </summary>
|
||||
/// <returns>最旧元素</returns>
|
||||
/// <exception cref="InvalidOperationException">缓冲区为空</exception>
|
||||
public readonly T GetOldest()
|
||||
{
|
||||
if (_count == 0)
|
||||
throw new InvalidOperationException("缓冲区为空");
|
||||
|
||||
return _buffer[_head];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -124,10 +124,10 @@ bool currentFrameSuccessForLock = IsTargetInBeam(missileDirection, targetDirecti
|
||||
添加了RCS波动的详细调试信息:
|
||||
|
||||
```csharp
|
||||
Debug.WriteLine($"[MMW_GUIDANCE] 目标 {target.Id}: 原始RCS: {rcsDbSm:F2} dBsm ({rcsLinear:F4} m²).");
|
||||
Debug.WriteLine($"[MMW_RCS计算] 目标 {target.Id}: 原始RCS: {rcsDbSm:F2} dBsm ({rcsLinear:F4} m²).");
|
||||
double rcsDbSmAfterSwerling = 10.0 * Math.Log10(rcsLinear);
|
||||
double rcsVariationDb = rcsDbSmAfterSwerling - rcsDbSm;
|
||||
Debug.WriteLine($"[MMW_GUIDANCE] 目标 {target.Id}: Swerling后RCS: {rcsDbSmAfterSwerling:F2} dBsm ({rcsLinear:F4} m²), 波动: {rcsVariationDb:+F2} dB.");
|
||||
Debug.WriteLine($"[MMW_RCS计算] 目标 {target.Id}: Swerling后RCS: {rcsDbSmAfterSwerling:F2} dBsm ({rcsLinear:F4} m²), 波动: {rcsVariationDb:+F2} dB.");
|
||||
```
|
||||
|
||||
## 技术原理
|
||||
|
||||
@ -194,6 +194,8 @@ GC频率: 优秀 ✅
|
||||
|
||||
#### 毫米波制导导弹
|
||||
|
||||
- 优化前:
|
||||
|
||||
=== 详细性能测试结果 ===
|
||||
|
||||
【基本统计】
|
||||
@ -225,8 +227,35 @@ GC频率: 优秀 ✅
|
||||
帧时间表现: 优秀 ✅
|
||||
内存管理: 优秀 ✅
|
||||
GC频率: 优秀 ✅
|
||||
|
||||
【潜在问题分析】
|
||||
|
||||
- 优化后:
|
||||
|
||||
=== 详细性能测试结果 ===
|
||||
【基本统计】
|
||||
测试时长: 30.0 秒
|
||||
总更新次数: 1417
|
||||
平均FPS: 47.2
|
||||
平均帧时间: 0.63 ms
|
||||
【帧时间分析】
|
||||
最小帧时间: 0.00 ms
|
||||
最大帧时间: 10.71 ms
|
||||
95%分位数: 2.78 ms
|
||||
99%分位数: 4.89 ms
|
||||
【内存使用分析】
|
||||
起始内存: 1.76 MB
|
||||
结束内存: 5.21 MB
|
||||
峰值内存: 11.70 MB
|
||||
内存增长: 3.45 MB
|
||||
平均内存增长率: 0.11 MB/s
|
||||
【垃圾回收分析】
|
||||
Gen0 GC次数: 25 (0.8 次/秒)
|
||||
Gen1 GC次数: 2 (0.1 次/秒)
|
||||
Gen2 GC次数: 1 (0.0 次/秒)
|
||||
总GC次数: 28
|
||||
【性能评级】
|
||||
帧时间表现: 优秀 ✅
|
||||
内存管理: 优秀 ✅
|
||||
GC频率: 优秀 ✅
|
||||
|
||||
#### 末敏弹
|
||||
|
||||
@ -261,8 +290,6 @@ GC频率: 优秀 ✅
|
||||
帧时间表现: 优秀 ✅
|
||||
内存管理: 优秀 ✅
|
||||
GC频率: 优秀 ✅
|
||||
|
||||
【潜在问题分析】
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user