diff --git a/TextLocator/Cache/LFUCache.cs b/TextLocator/Cache/LFUCache.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b6032142e881a51913607fab3f6e0ab6acf8f0e7
--- /dev/null
+++ b/TextLocator/Cache/LFUCache.cs
@@ -0,0 +1,157 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TextLocator.Cache
+{
+
+ ///
+ /// LFU(Least Frequently Used)缓存机制
+ /// 从数据集中,挑选最不经常使用的数据淘汰。
+ ///
+ public class LFUCache
+ {
+ ///
+ /// 数据键值对
+ ///
+ private Dictionary dataDic;
+ ///
+ /// 缓存频率数据节点
+ ///
+ private Dictionary> frequenNodeListDic;
+ ///
+ /// 缓存容量大小
+ ///
+ private int _capacity;
+ ///
+ /// 最小频率
+ ///
+ private int _minFreq;
+
+ ///
+ /// 构造函数
+ ///
+ /// 缓存池容量
+ public LFUCache(int capacity)
+ {
+ _capacity = capacity;
+ _minFreq = 0;
+
+ dataDic = new Dictionary(capacity);
+ frequenNodeListDic = new Dictionary>();
+
+ frequenNodeListDic.Add(0, new LinkedList());
+ }
+
+ ///
+ /// 获取缓存
+ ///
+ /// 接收数据类型
+ /// 缓存Key
+ /// 缓存Value
+ public T Get(string key)
+ {
+ // 验证缓存是否存在
+ if (!Exists(key))
+ return default(T);
+
+ // 获取缓存值
+ var value = dataDic[key].Value;
+ // 重新写入,频率计数器+1
+ Put(key, value);
+ try
+ {
+ // 返回Value
+ return (T)value;
+ }
+ catch
+ {
+ return default(T);
+ }
+ }
+
+ ///
+ /// 设置缓存
+ ///
+ /// 缓存Key
+ /// 缓存Value
+ public void Put(string key, object value)
+ {
+ // 如果容量为0,则返回
+ if (_capacity == 0)
+ return;
+
+ // 构造新的缓存对象
+ var newCacheData = new LFUCacheEntity { Key = key, Value = value, Frequen = 0 };
+
+ // 缓存已存在
+ if (dataDic.ContainsKey(key))
+ {
+ // 缓存数据对象
+ var cacheEntity = dataDic[key];
+
+ // 旧的计数器
+ var oldFrequen = cacheEntity.Frequen;
+ // 旧的计数器节点列表
+ var oldFrequenNodeList = frequenNodeListDic[oldFrequen];
+ // 从缓存频率数据节点
+ oldFrequenNodeList.Remove(cacheEntity);
+
+ // 频率计数器+1
+ var newFrequen = oldFrequen + 1;
+ // 缓存频率数据节点不存在
+ if (!frequenNodeListDic.ContainsKey(newFrequen))
+ {
+ // 新频率添加节点列表
+ frequenNodeListDic.Add(newFrequen, new LinkedList());
+ }
+
+ // 设置新缓存频率计数器
+ newCacheData.Frequen = newFrequen;
+ // 缓存频率数据节点添加新缓存
+ frequenNodeListDic[newFrequen].AddLast(newCacheData);
+ // 数据缓存对象设置新缓存
+ dataDic[key] = newCacheData;
+
+ // 缓存频率数据节点存在缓存 && 节点数据为0
+ if (frequenNodeListDic.ContainsKey(_minFreq) && frequenNodeListDic[_minFreq].Count == 0) {
+ // 记录访问频率
+ _minFreq = newFrequen;
+ }
+ return;
+ }
+
+ // 缓存池 超出容量
+ if (_capacity <= dataDic.Count)
+ {
+ // 根据记录的访问频率获取需要删除的节点列表
+ var deleteNodeList = frequenNodeListDic[_minFreq];
+ // 获取需要删除的节点,节点列表第一个元素
+ var deleteFirstNode = deleteNodeList.First;
+ // 删除节点列表第一个元素
+ deleteNodeList.RemoveFirst();
+ // 数据缓存吃删除第一个元素对应的Key
+ dataDic.Remove(deleteFirstNode.Value.Key);
+ }
+
+ // 缓存频率数据节点最后添加新缓存
+ frequenNodeListDic[0].AddLast(newCacheData);
+ // 数据缓存添加新缓存
+ dataDic.Add(key, newCacheData);
+ // 频率计数器归零
+ _minFreq = 0;
+ }
+
+ ///
+ /// 是否存在缓存
+ ///
+ ///
+ ///
+ public bool Exists(string key)
+ {
+ return dataDic.ContainsKey(key);
+ }
+ }
+}
diff --git a/TextLocator/Cache/LFUCacheEntity.cs b/TextLocator/Cache/LFUCacheEntity.cs
new file mode 100644
index 0000000000000000000000000000000000000000..6d6b83bf11417de8355e5a1f6cbf101e4ad6867e
--- /dev/null
+++ b/TextLocator/Cache/LFUCacheEntity.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TextLocator.Cache
+{
+ ///
+ /// LFU缓存对象
+ ///
+ public class LFUCacheEntity
+ {
+ ///
+ /// 缓存Key
+ ///
+ public string Key { get; set; }
+ ///
+ /// 缓存Value
+ ///
+ public object Value { get; set; }
+ ///
+ /// 缓存使用频率计数器
+ ///
+ public int Frequen { get; set; }
+ }
+}
diff --git a/TextLocator/Core/AppConst.cs b/TextLocator/Core/AppConst.cs
index 2851fb6376c7e7d6333f7d47acde71ff783c77ab..6ebd20c4c331c1547d9938c5dabe2a0ea95d58e6 100644
--- a/TextLocator/Core/AppConst.cs
+++ b/TextLocator/Core/AppConst.cs
@@ -36,6 +36,10 @@ namespace TextLocator.Core
/// 压缩包解析大小
///
public static int ZIP_FILE_SIZE_LIMIT = int.Parse(AppUtil.ReadValue("AppConfig", "ZipFileSizeLimit", "20000000"));
+ ///
+ /// 缓存池容量
+ ///
+ public static int CACHE_POOL_CAPACITY = int.Parse(AppUtil.ReadValue("AppConfig", "CachePoolCapacity", "100000"));
///
diff --git a/TextLocator/Properties/AssemblyInfo.cs b/TextLocator/Properties/AssemblyInfo.cs
index ec36ef2cc00ea7528086dcf1c52aca2c46f7064f..666cd99530fb84c218beae01cab722fa47d4a069 100644
--- a/TextLocator/Properties/AssemblyInfo.cs
+++ b/TextLocator/Properties/AssemblyInfo.cs
@@ -49,8 +49,8 @@ using System.Windows;
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.2.10")]
-[assembly: AssemblyFileVersion("1.2.10.1")]
+[assembly: AssemblyVersion("1.2.11")]
+[assembly: AssemblyFileVersion("1.2.11.0")]
// log4net
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
\ No newline at end of file
diff --git a/TextLocator/SettingWindow.xaml b/TextLocator/SettingWindow.xaml
index b2a4b640649e72435893325b6f79d5bc6c425fa7..53a033cc22972ff105733e18350101500e620e11 100644
--- a/TextLocator/SettingWindow.xaml
+++ b/TextLocator/SettingWindow.xaml
@@ -10,50 +10,64 @@
Title="设置" Height="380" Width="520" WindowStartupLocation="CenterScreen" WindowStyle="ToolWindow" ResizeMode="CanMinimize" Icon="/Resource/App.ico" Loaded="Window_Loaded" Closed="Window_Closed" >
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+
+
diff --git a/TextLocator/SettingWindow.xaml.cs b/TextLocator/SettingWindow.xaml.cs
index eb5ca680bf942b68bcceb78fc4351bca6ffc867d..947127b7ddda1433e4963ab387ec66ca897e28b2 100644
--- a/TextLocator/SettingWindow.xaml.cs
+++ b/TextLocator/SettingWindow.xaml.cs
@@ -65,6 +65,9 @@ namespace TextLocator
// 文件读取超时时间
this.FileReadTimeout.Text = AppConst.FILE_READ_TIMEOUT + "";
+
+ // 缓存池容量
+ this.CachePoolCapacity.Text = AppConst.CACHE_POOL_CAPACITY + "";
}
#region 保存并关闭
@@ -85,6 +88,9 @@ namespace TextLocator
// 文件读取超时时间
string fileReadTimeoutText = this.FileReadTimeout.Text;
+ // 缓存池容量
+ string cachePoolCapacityText = this.CachePoolCapacity.Text;
+
// 转换,验证
int minThreads = 0;
try
@@ -152,6 +158,21 @@ namespace TextLocator
return;
}
+ int cachePoolCapacity = 0;
+ try
+ {
+ cachePoolCapacity = int.Parse(cachePoolCapacityText);
+ } catch
+ {
+ Message.ShowWarning("MessageContainer", "缓存池容量设置错误");
+ return;
+ }
+ if (cachePoolCapacity < 50000 || cachePoolCapacity > 500000)
+ {
+ Message.ShowWarning("MessageContainer", "建议设置在5-50w范围内");
+ return;
+ }
+
// 刷新、保存
AppConst.THREAD_POOL_MIN_SIZE = minThreads;
AppConst.THREAD_POOL_MAX_SIZE = maxThreads;
@@ -166,6 +187,10 @@ namespace TextLocator
AppUtil.WriteValue("AppConfig", "FileReadTimeout", AppConst.FILE_READ_TIMEOUT + "");
log.Debug("修改文件读取超时时间:" + AppConst.FILE_READ_TIMEOUT);
+ AppConst.CACHE_POOL_CAPACITY = cachePoolCapacity;
+ AppUtil.WriteValue("AppConfig", "CachePoolCapacity", AppConst.CACHE_POOL_CAPACITY + "");
+ log.Debug("修改缓存池容量:" + AppConst.CACHE_POOL_CAPACITY);
+
this.Close();
}
#endregion
diff --git a/TextLocator/TextLocator.csproj b/TextLocator/TextLocator.csproj
index a913e9bdef3c3eb45926b9194a058017df0989dd..687fbb9cb9323832a7795bbc0c8be541f824d99e 100644
--- a/TextLocator/TextLocator.csproj
+++ b/TextLocator/TextLocator.csproj
@@ -177,6 +177,8 @@
MSBuild:Compile
Designer
+
+
diff --git a/TextLocator/Util/CacheUtil.cs b/TextLocator/Util/CacheUtil.cs
index 82b2c6d2165835deece2deb3585d351ad760b39b..0f53b3ecc232b526cc4f46fe9613c61ce9bf6384 100644
--- a/TextLocator/Util/CacheUtil.cs
+++ b/TextLocator/Util/CacheUtil.cs
@@ -1,4 +1,6 @@
using System.Collections.Generic;
+using TextLocator.Cache;
+using TextLocator.Core;
namespace TextLocator.Util
{
@@ -7,15 +9,22 @@ namespace TextLocator.Util
///
public class CacheUtil
{
- //缓存容器
- private static Dictionary cacheDic = new Dictionary();
+ ///
+ /// LFU缓存
+ ///
+ private static LFUCache _cache;
+
+ static CacheUtil()
+ {
+ _cache = new LFUCache(AppConst.CACHE_POOL_CAPACITY);
+ }
///
/// 添加缓存
///
public static void Add(string key, object value)
{
- cacheDic[key] = value;
+ _cache.Put(key, value);
}
///
@@ -23,11 +32,7 @@ namespace TextLocator.Util
///
public static T Get(string key)
{
- try
- {
- return (T)cacheDic[key];
- } catch { }
- return default(T);
+ return _cache.Get(key);
}
///
@@ -37,7 +42,7 @@ namespace TextLocator.Util
///
public static bool Exsits(string key)
{
- return cacheDic.ContainsKey(key);
+ return _cache.Exists(key);
}
}
}