【cfg】 解决FileRecordCacheManager不清除缓存,导致内存占用缓慢无限增大的bug

main
walon 2021-06-09 19:29:26 +08:00
parent e36468dcc8
commit ee217e1a32
2 changed files with 51 additions and 7 deletions

View File

@ -33,8 +33,6 @@ namespace Luban.Client
private static NLog.Logger s_logger;
private static MultiFileWatcher s_watcher;
private static void PrintUsage(string err)
{
Console.WriteLine("ERRORS:");
@ -166,7 +164,7 @@ Options:
{
GenOnce(options, profile);
s_watcher = new MultiFileWatcher(options.WatchDir, () => GenOnce(options, profile));
new MultiFileWatcher(options.WatchDir, () => GenOnce(options, profile));
}
}

View File

@ -2,6 +2,7 @@ using Luban.Job.Cfg.Datas;
using Luban.Job.Cfg.Defs;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
namespace Luban.Job.Cfg.Cache
{
@ -13,9 +14,30 @@ namespace Luban.Job.Cfg.Cache
{
private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger();
private const int CACHE_FILE_LOW_WATER_MARK = 5000;
private const int CACHE_FILE_HIGH_WATER_MARK = 8000;
public static FileRecordCacheManager Ins { get; } = new FileRecordCacheManager();
private readonly ConcurrentDictionary<(string, string, string, bool), (DefTable, List<DType>)> _caches = new ConcurrentDictionary<(string, string, string, bool), (DefTable, List<DType>)>();
class FileRecordCache
{
public DefTable Table { get; }
public List<DType> Records { get; }
public volatile int LastAccessTime;
public FileRecordCache(DefTable table, List<DType> records)
{
Table = table;
Records = records;
LastAccessTime = Bright.Time.TimeUtil.Now;
}
}
private readonly ConcurrentDictionary<(string, string, string, bool), FileRecordCache> _caches = new ConcurrentDictionary<(string, string, string, bool), FileRecordCache>();
private readonly object _shrinkLocker = new object();
public bool TryGetCacheLoadedRecords(DefTable table, string md5, string originFile, string sheetName, bool exportTestData, out List<DType> cacheRecords)
{
@ -25,9 +47,10 @@ namespace Luban.Job.Cfg.Cache
{
return false;
}
if (r.Item1.ValueTType.GetBeanAs<DefBean>().IsDefineEquals(table.ValueTType.GetBeanAs<DefBean>()))
r.LastAccessTime = Bright.Time.TimeUtil.Now;
if (r.Table.ValueTType.GetBeanAs<DefBean>().IsDefineEquals(table.ValueTType.GetBeanAs<DefBean>()))
{
cacheRecords = r.Item2;
cacheRecords = r.Records;
s_logger.Trace("hit cache. table:{table} file:{file} md5:{md5}", table.FullName, originFile, md5);
return true;
}
@ -39,7 +62,30 @@ namespace Luban.Job.Cfg.Cache
public void AddCacheLoadedRecords(DefTable table, string md5, string sheetName, bool exportTestData, List<DType> cacheRecords)
{
_caches[(table.Assembly.TimeZone.Id, md5, sheetName, exportTestData)] = (table, cacheRecords);
lock (_shrinkLocker)
{
_caches[(table.Assembly.TimeZone.Id, md5, sheetName, exportTestData)] = new FileRecordCache(table, cacheRecords);
if (_caches.Count > CACHE_FILE_HIGH_WATER_MARK)
{
s_logger.Info("ShrinkCaches. cache count > high CACHE_FILE_HIGH_WATER_MARK:{}", CACHE_FILE_HIGH_WATER_MARK);
ShrinkCaches();
}
}
}
private void ShrinkCaches()
{
if (_caches.Count < CACHE_FILE_HIGH_WATER_MARK)
{
return;
}
var cacheList = _caches.ToList();
cacheList.Sort((a, b) => a.Value.LastAccessTime - b.Value.LastAccessTime);
for (int i = 0; i < CACHE_FILE_HIGH_WATER_MARK - CACHE_FILE_LOW_WATER_MARK; i++)
{
_caches.Remove(cacheList[i].Key, out _);
}
s_logger.Info("ShrinkCaches. after shrink, cache file num:{}", _caches.Count);
}
}
}