347 lines
11 KiB
C#
347 lines
11 KiB
C#
using System;
|
||
using System.Collections.Concurrent;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
|
||
namespace NavisworksTransport.PathPlanning
|
||
{
|
||
/// <summary>
|
||
/// GridMap缓存项,包含网格地图和访问时间信息
|
||
/// </summary>
|
||
public class GridMapCacheItem
|
||
{
|
||
/// <summary>
|
||
/// 缓存的网格地图
|
||
/// </summary>
|
||
public GridMap GridMap { get; set; }
|
||
|
||
/// <summary>
|
||
/// 最后访问时间
|
||
/// </summary>
|
||
public DateTime LastAccessTime { get; set; }
|
||
|
||
/// <summary>
|
||
/// 创建时间
|
||
/// </summary>
|
||
public DateTime CreatedTime { get; set; }
|
||
|
||
/// <summary>
|
||
/// 访问次数
|
||
/// </summary>
|
||
public int AccessCount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 构造函数
|
||
/// </summary>
|
||
public GridMapCacheItem(GridMap gridMap)
|
||
{
|
||
GridMap = gridMap ?? throw new ArgumentNullException(nameof(gridMap));
|
||
LastAccessTime = DateTime.Now;
|
||
CreatedTime = DateTime.Now;
|
||
AccessCount = 1;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 记录访问
|
||
/// </summary>
|
||
public void RecordAccess()
|
||
{
|
||
LastAccessTime = DateTime.Now;
|
||
AccessCount++;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// GridMap缓存统计信息
|
||
/// </summary>
|
||
public class GridMapCacheStatistics
|
||
{
|
||
/// <summary>
|
||
/// 缓存命中次数
|
||
/// </summary>
|
||
public long HitCount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 缓存未命中次数
|
||
/// </summary>
|
||
public long MissCount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前缓存项数量
|
||
/// </summary>
|
||
public int CurrentCount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 最大缓存项数量
|
||
/// </summary>
|
||
public int MaxCapacity { get; set; }
|
||
|
||
/// <summary>
|
||
/// 被驱逐的缓存项数量
|
||
/// </summary>
|
||
public long EvictedCount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 累计节省的构建时间(毫秒)
|
||
/// </summary>
|
||
public long TotalTimeSavedMs { get; set; }
|
||
|
||
/// <summary>
|
||
/// 缓存命中率
|
||
/// </summary>
|
||
public double HitRate => HitCount + MissCount > 0 ? (double)HitCount / (HitCount + MissCount) : 0.0;
|
||
|
||
/// <summary>
|
||
/// 缓存使用率
|
||
/// </summary>
|
||
public double UsageRate => MaxCapacity > 0 ? (double)CurrentCount / MaxCapacity : 0.0;
|
||
|
||
/// <summary>
|
||
/// 重置统计信息
|
||
/// </summary>
|
||
public void Reset()
|
||
{
|
||
HitCount = 0;
|
||
MissCount = 0;
|
||
EvictedCount = 0;
|
||
TotalTimeSavedMs = 0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成统计报告
|
||
/// </summary>
|
||
public string GenerateReport()
|
||
{
|
||
return $"GridMap缓存统计 - 命中率: {HitRate:P2} ({HitCount}命中/{MissCount}未命中), " +
|
||
$"使用率: {UsageRate:P2} ({CurrentCount}/{MaxCapacity}), " +
|
||
$"驱逐次数: {EvictedCount}, 节省时间: {TotalTimeSavedMs/1000.0:F1}秒";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// GridMap缓存管理器
|
||
/// 使用LRU策略管理GridMap缓存,支持线程安全访问
|
||
/// </summary>
|
||
public class GridMapCache
|
||
{
|
||
private readonly ConcurrentDictionary<GridMapCacheKey, GridMapCacheItem> _cache;
|
||
private readonly object _cleanupLock = new object();
|
||
private readonly int _maxCapacity;
|
||
private readonly GridMapCacheStatistics _statistics;
|
||
|
||
/// <summary>
|
||
/// 获取缓存统计信息
|
||
/// </summary>
|
||
public GridMapCacheStatistics Statistics => _statistics;
|
||
|
||
/// <summary>
|
||
/// 构造函数
|
||
/// </summary>
|
||
/// <param name="maxCapacity">最大缓存容量,默认10个GridMap</param>
|
||
public GridMapCache(int maxCapacity = 10)
|
||
{
|
||
if (maxCapacity <= 0)
|
||
throw new ArgumentException("缓存容量必须大于0", nameof(maxCapacity));
|
||
|
||
_maxCapacity = maxCapacity;
|
||
_cache = new ConcurrentDictionary<GridMapCacheKey, GridMapCacheItem>();
|
||
_statistics = new GridMapCacheStatistics { MaxCapacity = maxCapacity };
|
||
|
||
LogManager.Info($"[GridMap缓存] 初始化完成,最大容量: {_maxCapacity}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取缓存的GridMap
|
||
/// </summary>
|
||
/// <param name="key">缓存键</param>
|
||
/// <param name="estimatedBuildTimeMs">预估的构建时间(用于统计节省时间)</param>
|
||
/// <returns>GridMap对象,如果不存在则返回null</returns>
|
||
public GridMap Get(GridMapCacheKey key, long estimatedBuildTimeMs = 0)
|
||
{
|
||
if (key == null)
|
||
return null;
|
||
|
||
if (_cache.TryGetValue(key, out var item))
|
||
{
|
||
// 记录访问
|
||
item.RecordAccess();
|
||
_statistics.HitCount++;
|
||
|
||
// 累计节省时间
|
||
if (estimatedBuildTimeMs > 0)
|
||
{
|
||
_statistics.TotalTimeSavedMs += estimatedBuildTimeMs;
|
||
}
|
||
|
||
LogManager.Info($"[GridMap缓存] 命中 - {key},访问次数: {item.AccessCount}");
|
||
return item.GridMap;
|
||
}
|
||
|
||
_statistics.MissCount++;
|
||
LogManager.Info($"[GridMap缓存] 未命中 - {key}");
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加GridMap到缓存
|
||
/// </summary>
|
||
/// <param name="key">缓存键</param>
|
||
/// <param name="gridMap">GridMap对象</param>
|
||
public void Put(GridMapCacheKey key, GridMap gridMap)
|
||
{
|
||
if (key == null || gridMap == null)
|
||
return;
|
||
|
||
var item = new GridMapCacheItem(gridMap);
|
||
|
||
// 添加或更新缓存项
|
||
_cache.AddOrUpdate(key, item, (k, existing) =>
|
||
{
|
||
LogManager.Debug($"[GridMap缓存] 更新现有项 - {key}");
|
||
return item;
|
||
});
|
||
|
||
// 更新统计信息
|
||
_statistics.CurrentCount = _cache.Count;
|
||
|
||
LogManager.Info($"[GridMap缓存] 添加 - {key},当前容量: {_cache.Count}/{_maxCapacity}");
|
||
LogManager.Info($"[GridMap缓存] GridMap统计: {gridMap.GetStatistics()}");
|
||
|
||
// 检查是否需要清理
|
||
if (_cache.Count > _maxCapacity)
|
||
{
|
||
CleanupCache();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查缓存中是否包含指定键
|
||
/// </summary>
|
||
/// <param name="key">缓存键</param>
|
||
/// <returns>是否包含</returns>
|
||
public bool ContainsKey(GridMapCacheKey key)
|
||
{
|
||
return key != null && _cache.ContainsKey(key);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除所有缓存
|
||
/// </summary>
|
||
public void Clear()
|
||
{
|
||
lock (_cleanupLock)
|
||
{
|
||
var count = _cache.Count;
|
||
_cache.Clear();
|
||
_statistics.CurrentCount = 0;
|
||
_statistics.Reset();
|
||
|
||
LogManager.Info($"[GridMap缓存] 清除所有缓存,共清除 {count} 项");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取缓存的所有键
|
||
/// </summary>
|
||
/// <returns>键列表</returns>
|
||
public IList<GridMapCacheKey> GetKeys()
|
||
{
|
||
return _cache.Keys.ToList();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清理缓存,使用LRU策略移除最少使用的项
|
||
/// </summary>
|
||
private void CleanupCache()
|
||
{
|
||
lock (_cleanupLock)
|
||
{
|
||
// 双重检查,避免重复清理
|
||
if (_cache.Count <= _maxCapacity)
|
||
return;
|
||
|
||
var targetCount = Math.Max(1, (int)(_maxCapacity * 0.7)); // 清理到70%容量
|
||
var itemsToRemove = _cache.Count - targetCount;
|
||
|
||
LogManager.Info($"[GridMap缓存] 开始LRU清理,当前: {_cache.Count},目标: {targetCount},需移除: {itemsToRemove}");
|
||
|
||
// 按最后访问时间排序,移除最久未访问的项
|
||
var sortedItems = _cache
|
||
.OrderBy(kvp => kvp.Value.LastAccessTime)
|
||
.ThenBy(kvp => kvp.Value.AccessCount) // 相同时间的情况下,优先移除访问次数少的
|
||
.Take(itemsToRemove)
|
||
.ToList();
|
||
|
||
int removedCount = 0;
|
||
foreach (var item in sortedItems)
|
||
{
|
||
if (_cache.TryRemove(item.Key, out _))
|
||
{
|
||
removedCount++;
|
||
_statistics.EvictedCount++;
|
||
LogManager.Debug($"[GridMap缓存] 移除 - {item.Key},最后访问: {item.Value.LastAccessTime:yyyy-MM-dd HH:mm:ss}");
|
||
}
|
||
}
|
||
|
||
_statistics.CurrentCount = _cache.Count;
|
||
LogManager.Info($"[GridMap缓存] LRU清理完成,实际移除: {removedCount},当前容量: {_cache.Count}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成缓存详细报告
|
||
/// </summary>
|
||
/// <returns>报告字符串</returns>
|
||
public string GenerateDetailedReport()
|
||
{
|
||
var report = new System.Text.StringBuilder();
|
||
|
||
report.AppendLine(_statistics.GenerateReport());
|
||
|
||
if (_cache.Count > 0)
|
||
{
|
||
report.AppendLine($"\n当前缓存项详情:");
|
||
var sortedItems = _cache
|
||
.OrderByDescending(kvp => kvp.Value.LastAccessTime)
|
||
.Take(5) // 只显示最近5项
|
||
.ToList();
|
||
|
||
foreach (var item in sortedItems)
|
||
{
|
||
var gridStats = item.Value.GridMap?.GetStatistics() ?? "N/A";
|
||
report.AppendLine($" {item.Key}");
|
||
report.AppendLine($" 访问{item.Value.AccessCount}次,最后访问: {item.Value.LastAccessTime:MM-dd HH:mm:ss}");
|
||
report.AppendLine($" GridMap: {gridStats}");
|
||
}
|
||
|
||
if (_cache.Count > 5)
|
||
{
|
||
report.AppendLine($" ... 还有 {_cache.Count - 5} 项");
|
||
}
|
||
}
|
||
|
||
return report.ToString();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 全局GridMap缓存管理器(单例)
|
||
/// </summary>
|
||
public static class GlobalGridMapCache
|
||
{
|
||
private static readonly Lazy<GridMapCache> _instance = new Lazy<GridMapCache>(() => new GridMapCache());
|
||
|
||
/// <summary>
|
||
/// 获取全局缓存实例
|
||
/// </summary>
|
||
public static GridMapCache Instance => _instance.Value;
|
||
|
||
/// <summary>
|
||
/// 重置全局缓存(主要用于测试)
|
||
/// </summary>
|
||
public static void Reset()
|
||
{
|
||
_instance.Value.Clear();
|
||
}
|
||
}
|
||
} |