perf: 回放优先用内存 LiveFrames — 仿真刚结束时避免读数据库

FrameDataStore:
- Flush() 后保留 LiveFrames 副本在内存
- BeginRecording() / Discard() 时清除 LiveFrames

ReplayController:
- LoadReplay(taskId, frameStore) 优先取 LiveFrames
- frameStore 为 null 或 LiveFrames 为空时回退读 SQLite
- SimulationRunner 暴露 FrameStore 供 ReplayController 传入
This commit is contained in:
tian 2026-06-17 16:07:24 +08:00
parent 4c2c18cfcc
commit 6098186f34
3 changed files with 25 additions and 6 deletions

View File

@ -14,6 +14,8 @@ namespace CounterDrone.Core.Simulation
private string _taskId = string.Empty;
public int RetentionDays { get; set; } = 180;
public int BufferedFrameCount { get; private set; }
/// <summary>仿真刚结束时保留内存快照支持快速回放。Flush 后自动清空。</summary>
public List<SimFrameRecord> LiveFrames { get; private set; } = new();
public FrameDataStore(IPathProvider paths)
{
@ -25,6 +27,7 @@ namespace CounterDrone.Core.Simulation
{
_taskId = taskId;
_buffer.Clear();
LiveFrames.Clear();
BufferedFrameCount = 0;
}
@ -60,7 +63,7 @@ namespace CounterDrone.Core.Simulation
{
var fr = _buffer[i];
var s = fr.Snapshot;
records.Add(new SimFrameRecord
var record = new SimFrameRecord
{
TaskId = _taskId, FrameIndex = fr.FrameIndex, Timestamp = fr.Timestamp,
EntityId = s.EntityId, EntityType = (int)s.EntityType,
@ -72,8 +75,13 @@ namespace CounterDrone.Core.Simulation
Models.EntityType.Cloud => $"{{\"radius\":{s.CloudRadius:F1},\"opacity\":{s.CloudOpacity:F2},\"phase\":{s.CloudPhase},\"elapsed\":{s.CloudElapsed:F1}}}",
_ => "{}",
},
});
};
records.Add(record);
}
// 保留一份在内存供快速回放
LiveFrames = records;
_buffer.Clear();
var dbPath = Path.Combine(_paths.GetFramesDir(), $"{_taskId}.db");
@ -84,7 +92,7 @@ namespace CounterDrone.Core.Simulation
db.InsertAll(records);
}
public void Discard() { _buffer.Clear(); BufferedFrameCount = 0; }
public void Discard() { _buffer.Clear(); LiveFrames.Clear(); BufferedFrameCount = 0; }
public List<SimFrameRecord> ReadFrames(string taskId, int fromFrame, int toFrame)
{

View File

@ -7,7 +7,7 @@ using UnityEngine;
namespace CounterDrone.Unity
{
/// <summary>回放控制器 — 从帧数据库读取历史仿真数据</summary>
/// <summary>回放控制器 — 仿真刚结束时用内存数据快速回放,历史仿真从数据库读取</summary>
public class ReplayController : MonoBehaviour
{
private FrameDataStore _frameStore;
@ -23,9 +23,19 @@ namespace CounterDrone.Unity
_frameStore = new FrameDataStore(_paths);
}
public void LoadReplay(string taskId)
/// <summary>加载回放数据:优先使用传入的 frameStore 内存数据(仿真刚结束),否则读数据库</summary>
public void LoadReplay(string taskId, FrameDataStore frameStore = null)
{
CurrentFrames = _frameStore.ReadFrames(taskId, 0, int.MaxValue);
if (frameStore != null && frameStore.LiveFrames.Count > 0)
{
_frameStore = frameStore;
CurrentFrames = _frameStore.LiveFrames;
}
else
{
_frameStore ??= new FrameDataStore(_paths);
CurrentFrames = _frameStore.ReadFrames(taskId, 0, int.MaxValue);
}
TotalFrames = CurrentFrames.Count > 0
? CurrentFrames.Max(f => f.FrameIndex) + 1

View File

@ -20,6 +20,7 @@ namespace CounterDrone.Unity
private SimulationEngine _engine;
private FrameDataStore _frameStore;
public FrameDataStore FrameStore => _frameStore;
private IScenarioService _scenario;
private IPathProvider _paths;
private string _taskId;