<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      代碼改變世界

      C#開源磁盤/內存緩存引擎

      2013-07-04 14:33  靈感之源  閱讀(6459)  評論(16)    收藏  舉報

      前言

      昨天寫了個 《基于STSdb和fastJson的磁盤/內存緩存》,大家可以先看看。下午用到業務系統時候,覺得可以改進一下,昨晚想了一個晚上,剛才重新實現一下。

      更新

      1. 增加了對批量處理的支持,寫操作速度提升5倍,讀操作提升100倍

      2. 增加了一個存儲provider,可以選擇不用STSdb做存儲,而用物理文件/Dictionary。

      3. 增加了空間回收

      4. 增加了對并發的支持

      需求

      業務系統用的是數據庫,數據量大,部分只讀或相對穩定業務查詢復雜,每次頁面加載都要花耗不少時間(不討論異步),覺得可以做一下高速緩存,譬如用nosql那種key/value快速存取結果

      目的

      提供一個簡單易用的解決緩存方案,可以根據數據的大小緩存到內存或者磁盤。

      實現

      存取

      方法1. 基于STSdb,提供高效的Key/Value存取,支持磁盤/內存,對Key無限制

      方法2. 基于直接物理文件/Dictionary。Key必須是基本類型,譬如int/long/uint/ulong/DateTime/string等。

      代碼

      代碼比較簡單,花了2個小時寫的,很多情況沒考慮,譬如磁盤空間/內存不足,自動回收過期緩存等,這些留給大家做家庭作業吧。另外,為了發布方便,STSdb和fastJson的代碼都合并到一個項目里。

      BaseCahce.cs

      這是一個抽象基類,提供存取接口。

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      
      namespace Com.SuperCache.Engine
      {
          public abstract class BaseCache
          {
              protected internal const string KeyExpiration = "Expiration";
      
              public abstract void Add<K>(string Category, K Key, object Data);
              public abstract void Add<K, V>(string Category, IEnumerable<KeyValuePair<K, V>> Items, DateTime? ExpirationDate);
              public abstract void Add<K>(string Category, K Key, object Data, DateTime? ExpirationDate);
              public abstract List<KeyValuePair<K, V>> Get<K, V>(string Category, IEnumerable<K> Keys);
              public abstract V Get<K, V>(string Category, K Key);
              public abstract void Recycle<K>( string Category, long Count);
          }
      }
      

        

        

      CahceEngine.cs

      主要調用緩存引擎

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using STSdb4.Database;
      using fastJSON;
      using System.IO;
      
      namespace Com.SuperCache.Engine
      {
          public enum CacheProviders
          {
              Default = 1,
              Raw = 2
          }
      
          public enum RecycleAlgorithms
          {
              None = 0,
              //LRU = 1,
              MRU = 2
          }
      
          public enum RecycleModes
          {
              None = 0,
              Passive = 1,
              Active = 2
          }
      
          public class CacheEngine
          {
              private BaseCache cacheProvider = null;
      
              public CacheEngine(string DataPath)
                  : this(CacheProviders.Default, DataPath, RecycleAlgorithms.None, 0, 0, RecycleModes.None)
              {
              }
      
              public CacheEngine(CacheProviders Provider, string DataPath, RecycleAlgorithms RecycleAlgorithm, int MaxCount, int Threshold, RecycleModes RecycleMode)
              {
                  switch (Provider)
                  {
                      case CacheProviders.Default:
                          cacheProvider = new STSdbCache(DataPath, RecycleAlgorithm, MaxCount, Threshold, RecycleMode);
                          break;
                      case CacheProviders.Raw:
                          cacheProvider = new RawCache(DataPath, RecycleAlgorithm, MaxCount, Threshold, RecycleMode);
                          break;
                      default:
                          break;
                  }
              }
      
              public void Add<K>(string Category, K Key, object Data)
              {
                  cacheProvider.Add<K>(Category, Key, Data);
              }
      
              public void Add<K, V>(string Category, IEnumerable<KeyValuePair<K, V>> Items, DateTime? ExpirationDate)
              {
                  cacheProvider.Add<K, V>(Category, Items, ExpirationDate);
              }
      
              public void Add<K>(string Category, K Key, object Data, DateTime? ExpirationDate)
              {
                  cacheProvider.Add<K>(Category, Key, Data, ExpirationDate);
              }
      
              public List<KeyValuePair<K, V>> Get<K, V>(string Category, IEnumerable<K> Keys)
              {
                  return cacheProvider.Get<K, V>(Category, Keys);
              }
      
              public V Get<K, V>(string Category, K Key)
              {
                  return cacheProvider.Get<K, V>(Category, Key);
              }
      
          }
      }
      

        

        

        

      STSdbCache.cs

      STSdb存儲引擎  

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using STSdb4.Database;
      using fastJSON;
      using System.IO;
      
      namespace Com.SuperCache.Engine
      {
          public class STSdbCache : BaseCache
          {
              private const string UsageStat = "SuperCacheUsageStat";
              private string dataPath;
              private static IStorageEngine memoryInstance = null;
              private static object syncRoot = new object();
              private bool isMemory = false;
              private RecycleAlgorithms recycleAlgorithm;
              private int maxCount;
              private int threshold;
              private RecycleModes recycleMode;
      
              public STSdbCache(string DataPath, RecycleAlgorithms RecycleAlgorithm, int MaxCount, int Threshold, RecycleModes RecycleMode)
              {
                  dataPath = DataPath;
                  if (!dataPath.EndsWith(Path.DirectorySeparatorChar.ToString()))
                      dataPath += Path.DirectorySeparatorChar;
      
                  isMemory = string.IsNullOrEmpty(DataPath);
      
                  recycleAlgorithm = RecycleAlgorithm;
                  maxCount = MaxCount;
                  threshold = Threshold;
                  recycleMode = RecycleMode;
              }
      
              public override void Add<K>(string Category, K Key, object Data)
              {
                  Add(Category, Key, Data, null);
              }
      
              private IStorageEngine Engine
              {
                  get
                  {
                      if (isMemory)
                      {
                          lock (syncRoot)
                          {
                              if (memoryInstance == null)
                                  memoryInstance = STSdb.FromMemory();
                          }
                          return memoryInstance;
                      }
                      else
                          return STSdb.FromFile(GetFile(false), GetFile(true));
                  }
              }
      
              private string GetExpirationTable(string Category)
              {
                  return KeyExpiration + "_" + Category;
              }
      
              public override void Add<K, V>(string Category, IEnumerable<KeyValuePair<K, V>> Items, DateTime? ExpirationDate)
              {
                  long count = 0;
      
                  lock (syncRoot)
                  {
                      var engine = Engine;
                      var table = engine.OpenXIndex<K, string>(Category);
                      var expiration = engine.OpenXIndex<K, DateTime>(GetExpirationTable(Category));
      
                      //track recycle
                      IIndex<K, int> usage = null;
                      if (recycleAlgorithm != RecycleAlgorithms.None)
                          usage = engine.OpenXIndex<K, int>(UsageStat);
      
                      Items.ForEach(i =>
                          {
                              var key = i.Key;
                              var data = i.Value;
                              //will only serialize object other than string
                              var result = typeof(V) == typeof(string) ? data as string : JSON.Instance.ToJSON(data);
                              table[key] = result;
                              table.Flush();
      
                              //specify expiration
                              //default 30 mins to expire from now
                              var expirationDate = ExpirationDate == null || ExpirationDate <= DateTime.Now ? DateTime.Now.AddMinutes(30) : (DateTime)ExpirationDate;
                              expiration[key] = expirationDate;
                              expiration.Flush();
      
                              //track recycle
                              if (usage != null)
                              {
                                  usage[key] = 0;
                                  if (recycleMode == RecycleModes.Active)
                                      Recycle<K>(Category, usage.Count());
                              }
                          });
      
                      if (usage != null)
                          count = usage.Count();
      
                      engine.Commit();
      
                      //only dispose disk-based engine
                      if (!isMemory)
                          engine.Dispose();
                  }
      
                  if (recycleMode == RecycleModes.Passive)
                      Recycle<K>(Category, count);
              }
      
              public override void Add<K>(string Category, K Key, object Data, DateTime? ExpirationDate)
              {
                  Add<K, object>(Category, new List<KeyValuePair<K, object>> { new KeyValuePair<K, object>(Key, Data) }, ExpirationDate);
              }
      
              private string GetFile(bool IsData)
              {
                  if (!Directory.Exists(dataPath))
                      Directory.CreateDirectory(dataPath);
                  return dataPath + "SuperCache." + (IsData ? "dat" : "sys");
              }
      
              public override List<KeyValuePair<K, V>> Get<K, V>(string Category, IEnumerable<K> Keys)
              {
                  var result = new List<KeyValuePair<K, V>>();
                  lock (syncRoot)
                  {
                      var engine = Engine;
                      var table = engine.OpenXIndex<K, string>(Category);
                      var expiration = engine.OpenXIndex<K, DateTime>(GetExpirationTable(Category));
                      var isCommitRequired = false;
      
                      //track recycle
                      IIndex<K, int> usage = null;
                      if (recycleAlgorithm != RecycleAlgorithms.None)
                          usage = engine.OpenXIndex<K, int>(UsageStat);
      
                      Keys.ForEach(key =>
                          {
                              string buffer;
                              V value;
                              if (table.TryGet(key, out buffer))
                              {
                                  //will only deserialize object other than string
                                  value = typeof(V) == typeof(string) ? (V)(object)buffer : JSON.Instance.ToObject<V>(buffer);
                                  bool needUpdate = true;
                                  DateTime expirationDate;
                                  //get expiration date
                                  if (expiration.TryGet(key, out expirationDate))
                                  {
                                      //expired
                                      if (expirationDate < DateTime.Now)
                                      {
                                          value = default(V);
                                          table.Delete(key);
                                          table.Flush();
                                          expiration.Delete(key);
                                          expiration.Flush();
                                          isCommitRequired = true;
                                          needUpdate = false;
                                      }
                                  }
      
                                  //track recycle
                                  if (usage != null && needUpdate)
                                  {
                                      usage[key]++;
                                      isCommitRequired = true;
                                  }
                              }
                              else
                                  value = default(V);
      
                              result.Add(new KeyValuePair<K, V>(key, value));
                          });
      
                      //only need to commit write actions
                      if (isCommitRequired)
                          engine.Commit();
      
                      //only dispose disk-based engine
                      if (!isMemory)
                          engine.Dispose();
                  }
                  return result;
              }
      
              public override V Get<K, V>(string Category, K Key)
              {
                  var buffer = Get<K, V>(Category, new K[] { Key });
                  var result = buffer.FirstOrDefault();
                  return result.Value;
              }
      
              public override void Recycle<K>(string Category, long Count)
              {
                  if (Count < maxCount)
                      return;
      
                  switch (recycleAlgorithm)
                  {
                      case RecycleAlgorithms.MRU:
                          lock (syncRoot)
                          {
                              var engine = Engine;
                              var table = engine.OpenXIndex<K, string>(Category);
                              var expiration = engine.OpenXIndex<K, DateTime>(GetExpirationTable(Category));
                              var usage = engine.OpenXIndex<K, int>(UsageStat);
                              //find out expired items
                              var expired = expiration.Where(e => e.Value < DateTime.Now);
                              expired.ForEach(e =>
                                  {
                                      table.Delete(e.Key);
                                      expiration.Delete(e.Key);
                                      usage.Delete(e.Key);
                                  });
      
                              //find out least used items
                              var leastUsed = usage.OrderByDescending(s => s.Value).Skip(maxCount - threshold);
                              leastUsed.ForEach(u =>
                              {
                                  table.Delete(u.Key);
                                  expiration.Delete(u.Key);
                                  usage.Delete(u.Key);
                              });
      
                              table.Flush();
                              expiration.Flush();
                              usage.Flush();
                              engine.Commit();
      
                              if (!isMemory)
                                  engine.Dispose();
                          }
                          break;
                      default:
                          break;
                  }
              }
          }
      }
      

        

        

      RawCache.cs

      物理文件/Dictionary引擎

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using STSdb4.Database;
      using fastJSON;
      using System.IO;
      
      namespace Com.SuperCache.Engine
      {
          public class RawCache : BaseCache
          {
              private const string ExpirationFileExtension = "exp";
              private const string DataFileExtension = "dat";
              private const string statFile = "SuperCache.sta";
              private string dataPath;
              private static Dictionary<string, object> memoryData = new Dictionary<string, object>();
              private static Dictionary<string, DateTime?> memoryExpiration = new Dictionary<string, DateTime?>();
              private static object syncRoot = new object();
              private bool isMemory = false;
              private RecycleAlgorithms recycleAlgorithm;
              private int maxCount;
              private int threshold;
              private static Dictionary<string, KeyValue> usageStat = new Dictionary<string, KeyValue>();
              private Dictionary<string, KeyValuePair<DateTime, string>> expiredFiles = new Dictionary<string, KeyValuePair<DateTime, string>>();
              private RecycleModes recycleMode;
      
              public RawCache(string DataPath, RecycleAlgorithms RecycleAlgorithm, int MaxCount, int Threshold, RecycleModes RecycleMode)
              {
                  dataPath = DataPath;
                  if (!dataPath.EndsWith(Path.DirectorySeparatorChar.ToString()))
                      dataPath += Path.DirectorySeparatorChar;
      
                  isMemory = string.IsNullOrEmpty(DataPath);
      
                  recycleAlgorithm = RecycleAlgorithm;
                  maxCount = MaxCount;
                  threshold = Threshold;
                  recycleMode = RecycleMode;
              }
      
              public override void Add<K>(string Category, K Key, object Data)
              {
                  Add(Category, Key, Data, null);
              }
      
              private string GetExpirationTable(string Category)
              {
                  return KeyExpiration + "_" + Category;
              }
      
              public override void Add<K, V>(string Category, IEnumerable<KeyValuePair<K, V>> Items, DateTime? ExpirationDate)
              {
                  long count = 0;
      
                  lock (syncRoot)
                  {
                      Items.ForEach(i =>
                          {
                              var key = i.Key;
                              var data = i.Value;
                              var cacheKey = GetKey(Category, key.ToString());
      
                              if (isMemory)
                              {
                                  memoryData[cacheKey] = data;
                                  memoryExpiration[cacheKey] = ExpirationDate;
      
                                  //recycle algo
                                  switch (recycleAlgorithm)
                                  {
                                      case RecycleAlgorithms.MRU:
                                          usageStat[cacheKey] = new KeyValue(string.Empty, 0);
                                          if (recycleMode == RecycleModes.Active)
                                              Recycle<K>(Category, memoryData.Count);
                                          break;
                                      default:
                                          break;
                                  }
                              }
                              else
                              {
                                  //will only serialize object other than string
                                  var result = typeof(V) == typeof(string) ? data as string : JSON.Instance.ToJSON(data);
                                  var fileKey = key.ToString();
                                  var dataFile = GetFile(Category, fileKey, true);
                                  bool exists = File.Exists(dataFile);
                                  File.WriteAllText(dataFile, result);
      
                                  //specify expiration
                                  //default 30 mins to expire from now
                                  var expirationDate = ExpirationDate == null || ExpirationDate <= DateTime.Now ? DateTime.Now.AddMinutes(30) : (DateTime)ExpirationDate;
                                  var expirationFile = GetFile(Category, fileKey, false);
                                  File.WriteAllText(expirationFile, expirationDate.ToString());
      
                                  //recycle algo
                                  if (recycleAlgorithm != RecycleAlgorithms.None)
                                  {
                                      var statFilePath = dataPath + statFile;
                                      if (File.Exists(statFilePath))
                                      {
                                          var buffer = File.ReadAllText(statFilePath);
                                          count = Convert.ToInt32(buffer);
                                      }
                                      if (!exists)
                                      {
                                          count++;
                                          File.WriteAllText(statFilePath, count.ToString());
                                      }
                                      switch (recycleAlgorithm)
                                      {
                                          case RecycleAlgorithms.MRU:
                                              usageStat[cacheKey] = new KeyValue(expirationFile, 0);
                                              expiredFiles[cacheKey] = new KeyValuePair<DateTime, string>(expirationDate, expirationFile);
                                              if (recycleMode == RecycleModes.Active)
                                                  Recycle<K>(Category, count);
                                              break;
                                          default:
                                              break;
                                      }
                                  }
                              }
                          });
      
                      if (recycleAlgorithm != RecycleAlgorithms.None && recycleMode == RecycleModes.Passive)
                      {
                          if (isMemory)
                              count = memoryData.Count;
                          Recycle<K>(Category, count);
                      }
                  }
              }
      
              public override void Add<K>(string Category, K Key, object Data, DateTime? ExpirationDate)
              {
                  Add<K, object>(Category, new List<KeyValuePair<K, object>> { new KeyValuePair<K, object>(Key, Data) }, ExpirationDate);
              }
      
              private string GetFile(string Category, string FileName, bool IsData)
              {
                  var path = dataPath + Category.NormalizeFileName() + @"\";
                  if (!Directory.Exists(path))
                      Directory.CreateDirectory(path);
                  return path + FileName.NormalizeFileName() + "." + (IsData ? "dat" : ExpirationFileExtension);
              }
      
              private string GetKey(string Category, string Key)
              {
                  return Category + "_" + Key;
              }
      
              public override List<KeyValuePair<K, V>> Get<K, V>(string Category, IEnumerable<K> Keys)
              {
                  var result = new List<KeyValuePair<K, V>>();
                  lock (syncRoot)
                  {
                      Keys.ForEach(key =>
                          {
                              string buffer;
                              V value;
                              var cacheKey = GetKey(Category, key.ToString());
                              if (isMemory)
                              {
                                  object memBuffer;
                                  if (memoryData.TryGetValue(cacheKey, out memBuffer))
                                  {
                                      //track recycle
                                      switch (recycleAlgorithm)
                                      {
                                          case RecycleAlgorithms.MRU:
                                              usageStat[cacheKey].Value++;
                                              break;
                                          default:
                                              break;
                                      }
      
                                      value = (V)memBuffer;
                                      DateTime? expirationDate;
                                      if (memoryExpiration.TryGetValue(cacheKey, out expirationDate))
                                      {
                                          //expired
                                          if (expirationDate != null && (DateTime)expirationDate < DateTime.Now)
                                          {
                                              value = default(V);
                                              memoryData.Remove(cacheKey);
                                              memoryExpiration.Remove(cacheKey);
                                          }
                                      }
                                  }
                                  else
                                      value = default(V);
                              }
                              else
                              {
                                  var dataFilePath = GetFile(Category, key.ToString(), true);
                                  if (File.Exists(dataFilePath))
                                  {
                                      buffer = File.ReadAllText(dataFilePath);
      
                                      //track recycle
                                      switch (recycleAlgorithm)
                                      {
                                          case RecycleAlgorithms.MRU:
                                              usageStat[cacheKey].Value++;
                                              break;
                                          default:
                                              break;
                                      }
      
                                      //will only deserialize object other than string
                                      value = typeof(V) == typeof(string) ? (V)(object)buffer : JSON.Instance.ToObject<V>(buffer);
                                      DateTime expirationDate;
                                      var expirationFilePath = GetFile(Category, key.ToString(), false);
                                      if (File.Exists(expirationFilePath))
                                      {
                                          buffer = File.ReadAllText(expirationFilePath);
                                          expirationDate = Convert.ToDateTime(buffer);
                                          //expired
                                          if (expirationDate < DateTime.Now)
                                          {
                                              value = default(V);
                                              File.Delete(dataFilePath);
                                              File.Delete(expirationFilePath);
                                          }
                                      }
                                  }
                                  else
                                      value = default(V);
                              }
      
                              result.Add(new KeyValuePair<K, V>(key, value));
                          });
                  }
                  return result;
              }
      
              public override V Get<K, V>(string Category, K Key)
              {
                  var buffer = Get<K, V>(Category, new K[] { Key });
                  var result = buffer.FirstOrDefault();
                  return result.Value;
              }
      
              public override void Recycle<K>(string Category, long Count)
              {
                  if (Count < maxCount)
                      return;
      
                  switch (recycleAlgorithm)
                  {
                      case RecycleAlgorithms.MRU:
                          lock (syncRoot)
                          {
                              var recycledFileCount = 0;
      
                              if (isMemory)
                              {
                                  //find out expired items
                                  var memExpired = memoryExpiration.Where(e => e.Value != null && (DateTime)e.Value < DateTime.Now);
                                  memExpired.ForEach(u =>
                                  {
                                      memoryData.Remove(u.Key);
                                      memoryExpiration.Remove(u.Key);
                                      usageStat.Remove(u.Key);
                                  });
                              }
                              else
                              {
                                  if (expiredFiles.Count == 0)
                                  {
                                      Directory.GetFiles(dataPath, "*." + ExpirationFileExtension).ForEach(f =>
                                          {
                                              var buffer = File.ReadAllText(f);
                                              var expirationDate = Convert.ToDateTime(buffer);
                                              expiredFiles[Path.GetFileNameWithoutExtension(f)] = new KeyValuePair<DateTime, string>(expirationDate, f);
                                          });
                                  }
                                  //find out expired items
                                  var fileExpired = expiredFiles.Where(e => e.Value.Key < DateTime.Now);
                                  fileExpired.ForEach(u =>
                                  {
                                      var dataFile = Path.ChangeExtension(u.Value.Value, DataFileExtension);
                                      File.Delete(dataFile);
                                      File.Delete(u.Value.Value);
                                      usageStat.Remove(u.Key);
                                      recycledFileCount++;
                                  });
                              }
      
                              //find out least used items
                              var leastUsed = usageStat.OrderByDescending(s => s.Value.Value).Skip(maxCount - threshold);
                              leastUsed.ForEach(u =>
                                  {
                                      if (isMemory)
                                      {
                                          memoryData.Remove(u.Key);
                                          memoryExpiration.Remove(u.Key);
                                      }
                                      else
                                      {
                                          var dataFile = Path.ChangeExtension(u.Value.Key, DataFileExtension);
                                          if (File.Exists(dataFile))
                                          {
                                              recycledFileCount++;
                                              File.Delete(dataFile);
                                          }
                                          if (File.Exists(u.Value.Key))
                                              File.Delete(u.Value.Key);
                                      }
                                      usageStat.Remove(u.Key);
                                  });
      
                              if (!isMemory)
                              {
                                  var statFilePath = dataPath + statFile;
                                  var count = 0;
                                  if (File.Exists(statFilePath))
                                  {
                                      var buffer = File.ReadAllText(statFilePath);
                                      count = Convert.ToInt32(buffer);
                                  }
                                  count = count - recycledFileCount;
                                  if (count < 0)
                                      count = 0;
                                  File.WriteAllText(statFilePath, count.ToString());
                              }
                          }
                          break;
                      default:
                          break;
                  }
              }
          }
      }
      

        

      Extensions.cs

      擴展函數

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.IO;
      
      namespace Com.SuperCache.Engine
      {
          public static class Extensions
          {
              public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
              {
                  if (source != null)
                  {
                      foreach (var item in source)
                      {
                          action(item);
                      }
                  }
              }
      
              public static string NormalizeFileName(this string FileName)
              {
                  var result = FileName;
                  Path.GetInvalidFileNameChars().ForEach(c =>
                      {
                          result = result.Replace(c.ToString(), string.Empty);
                      });
                  return result;
              }
          }
      }
      

        

      新建

      構造CacheEngine需要傳遞緩存保存到哪個文件夾。

      基于內存

      如果你不喜歡基于磁盤的緩存,可以使用基于內存,構造函數傳遞空字符串便可。

      增加/更新

      同一個方法:Add。用戶可以指定類型(Category),譬如User,Employee等。鍵(Key)支持泛型,值(Data)是object。有一個overload是過期日期(ExpirationDate),默認當前時間30分鐘后

      獲取

      Get方法需要指定類型(Category)和鍵(Key)。

       

      例子

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading;
      using System.Threading.Tasks;
      using System.Diagnostics;
      using Com.SuperCache.Engine;
      
      namespace Com.SuperCache.Test
      {
          public class Foo
          {
              public string Name { get; set; }
              public int Age { get; set; }
              public double? Some { get; set; }
              public DateTime? Birthday { get; set; }
          }
      
          class Program
          {
              static void Main(string[] args)
              {
                  //TestAddGet();
      
                  //Thread.Sleep(4000);
                  //TestExpiration();
      
                  TestDefaultDiskPerformance();
                  TestDefaultMemoryPerformance();
                  TestRawDiskPerformance();
                  TestRawMemoryPerformance();
      
                  //TestConcurrent();
      
                  Console.Read();
              }
      
              private static void TestConcurrent()
              {
                  var w = new Stopwatch();
                  w.Start();
                  Parallel.For(1, 3, (a) =>
                      {
                          var employees = Enumerable.Range((a - 1) * 1000, a * 1000).Select(i => new KeyValuePair<int, string>(i, "Wilson " + i + " Chen"));
                          var engine = new CacheEngine(@"..\..\data");
                          engine.Add<int, string>("Employee", employees, DateTime.Now.AddMinutes(1));
                      });
                  w.Stop();
                  Console.WriteLine("add:" + w.Elapsed);
      
                  var engine2 = new CacheEngine(@"..\..\data");
                  var o = engine2.Get<int, string>("Employee", 1005);
                  Console.WriteLine(o);
              }
      
              private static void TestDefaultDiskPerformance()
              {
                  TestPerformance(CacheProviders.Default, @"..\..\data");
              }
      
              private static void TestDefaultMemoryPerformance()
              {
                  TestPerformance(CacheProviders.Default, string.Empty);
              }
      
              private static void TestRawDiskPerformance()
              {
                  TestPerformance(CacheProviders.Raw, @"..\..\data");
              }
      
              private static void TestRawMemoryPerformance()
              {
                  TestPerformance(CacheProviders.Raw, string.Empty);
              }
      
              private static void TestPerformance(CacheProviders Provider, string DataPath)
              {
                  Console.WriteLine("Performance Test: " + Provider.ToString() + ", " + (string.IsNullOrEmpty(DataPath) ? "Memory" : DataPath));
                  var engine = new CacheEngine(Provider, DataPath, RecycleAlgorithms.MRU, 900, 100, RecycleModes.Passive);
                  var w = new Stopwatch();
      
                  w.Start();
                  var employees = Enumerable.Range(0, 1000).Select(i => new KeyValuePair<int, string>(i, "Wilson " + i + " Chen"));
                  engine.Add<int, string>("Employee", employees, DateTime.Now.AddMinutes(1));
                  w.Stop();
                  Console.WriteLine("add:" + w.Elapsed);
      
                  /*w.Restart();
                  employees.ForEach(key =>
                      {
                          var o1 = engine.Get<int, string>("Employee", key.Key);
                      });
                  w.Stop();
                  Console.WriteLine("individual get:" + w.Elapsed);*/
      
                  w.Restart();
                  var keys = employees.Select(i => i.Key);
                  var o = engine.Get<int, string>("Employee", keys);
                  w.Stop();
                  Console.WriteLine("get:" + w.Elapsed);
                  Console.WriteLine();
              }
      
              private static void TestExpiration()
              {
                  var engine = new CacheEngine(@"..\..\data");
                  var o = engine.Get<string, Foo>("User", "wchen");
                  Console.WriteLine(o != null ? o.Name : "wchen does not exist or expired");
              }
      
              private static void TestAddGet()
              {
                  var engine = new CacheEngine(@"..\..\data");
                  var f = new Foo { Name = "Wilson Chen", Age = 30, Birthday = DateTime.Now, Some = 123.456 };
                  engine.Add("User", "wchen", f, DateTime.Now.AddSeconds(5));
      
                  var o = engine.Get<string, Foo>("User", "wchen");
                  Console.WriteLine(o.Name);
      
                  var o4 = engine.Get<string, Foo>("User", "foo");
                  Console.WriteLine(o4 != null ? o4.Name : "foo does not exist");
      
                  var o3 = engine.Get<string, string>("PlainText", "A");
                  Console.WriteLine(o3 ?? "A does not exist");
              }
          }
      }
      

        

        

       

      性能

      通過上述性能測試例子,你會發現STSdb的磁盤存取速度要比一個記錄對應一個物理文件快。想了解更多,請訪問官方網站

      測試條件:1000條記錄,7200RPM磁盤,i7。

      引擎 介質 寫入 讀取
      STSdb 磁盤 0.4s 0.07s
        內存 0.06s 0.02s
      Raw 磁盤 1.0s 0.56s
        內存  0.01s 0.002s

       

         

      說明

      項目中引用了System.Management是因為STSdb支持內存數據庫,需要判斷最大物理內存。如果不喜歡,大家可以移除引用,并且去掉STSdb4.Database.STSdb.FromMemory方法便可。

      下載

      點擊這里下載

      主站蜘蛛池模板: 无码A级毛片免费视频下载| 精品少妇人妻av无码专区| 国产黄色三级三级看三级| 国产精品亚洲二区在线播放| 好吊视频在线一区二区三区| 精品国产成人一区二区| 日韩精品无码一区二区三区视频| 91久久久久无码精品露脸| 亚洲中文精品一区二区| 亚洲国产午夜理论片不卡| 久久久久无码精品国产AV| 亚洲av片在线免费观看| 国产成人a在线观看视频免费| 本溪市| 亚洲熟妇色xxxxx欧美老妇 | 无码人妻久久久一区二区三区| 果冻传媒一区二区天美传媒| 亚洲精品一区二区美女| 午夜免费福利小电影| 亚洲午夜激情久久加勒比| 国产人妇三级视频在线观看| 午夜精品久久久久久久爽| 丁香五月婷激情综合第九色| 欧美成人精品手机在线| 亚洲国产精品久久综合网| 国产97色在线 | 免费| а∨天堂一区中文字幕| 国产午夜福利精品久久不卡| 国产在线一区二区不卡| 99在线精品国自产拍中文字幕| 日韩有码中文字幕av| 日本无人区一区二区三区| 艳妇乳肉豪妇荡乳av无码福利| 天天做天天爱夜夜夜爽毛片| 久久综合香蕉国产蜜臀av| 高中女无套中出17p| 亚洲av无码专区在线厂| 曰韩精品无码一区二区三区视频| 欧美成人看片黄A免费看| 亚洲国产精品综合久久网络| 亚洲欧美人成电影在线观看|