• 改造LRU Cache for Windows Phone 7


    LRU是Least Recently Used最近最少使用算法,即最近最少使用页面置换算法,是为虚拟页式存储管理服务的。

    关于操作系统的内存管理,如何节省利用容量不大的内存为最多的进程提供资源,一直是研究的重要方向。

    而内存的虚拟存储管理,是现在最通用,最成功的方式——在内存有限的情况下,扩展一部分外存作为虚拟内存,真正的内存只存储当前运行时所用得到信息。

    不重复造轮子了 下面是C#方式写的开源代码,我们改造一下让他适用于 WP7

    http://lrucache.codeplex.com/

    主要改造如下: 用lock 替代过期的线程锁定代码,我不需要时间参数来LRU 所以也删掉了时间检测尽量提升性能!

    不多说代码如下:

      1 namespace Utilities
    2 {
    3 using System;
    4 using System.Collections.Generic;
    5 using System.Diagnostics;
    6 using System.Threading;
    7
    8 ////This class implements an LRU based cache. Uses a linked list to keep track of node usage
    9 ////Clients should use the following methods:
    10 ////AddObject(TKey key, TValue cacheObject)
    11 ////TValue GetObject(TKey key)
    12 public class LruCache<TKey, TValue> where TValue : class
    13 {
    14 private readonly Dictionary<TKey, NodeInfo> cachedNodesDictionary = new Dictionary<TKey, NodeInfo>();
    15 private readonly LinkedList<NodeInfo> lruLinkedList = new LinkedList<NodeInfo>();
    16
    17 private readonly int maxSize;
    18 // private readonly TimeSpan timeOut;
    19
    20 // private static readonly ReaderWriterLockSlim rwl = new ReaderWriterLockSlim();
    21
    22 // private Timer cleanupTimer;
    23
    24 public LruCache(int maxCacheSize, int memoryRefreshInterval)
    25 {
    26 // this.timeOut = itemExpiryTimeout;
    27 this.maxSize = maxCacheSize;
    28 AutoResetEvent autoEvent = new AutoResetEvent(false);
    29 // TimerCallback tcb = this.RemoveExpiredElements;
    30 // this.cleanupTimer = new Timer(tcb, autoEvent, 0, memoryRefreshInterval);
    31 }
    32
    33 public void AddObject(TKey key, TValue cacheObject)
    34 {
    35 if (key == null)
    36 {
    37 throw new ArgumentNullException("key");
    38 }
    39
    40 // Trace.WriteLine(string.Format("Adding a cache object with key: {0}", key.ToString()));
    41 // rwl.EnterWriteLock();
    42 try
    43 {
    44 lock (cacheObject)
    45 {
    46 NodeInfo node;
    47 if (this.cachedNodesDictionary.TryGetValue(key, out node))
    48 {
    49 this.Delete(node);
    50 }
    51 this.ShrinkToSize(this.maxSize - 1);
    52 this.CreateNodeandAddtoList(key, cacheObject);
    53 }
    54 }
    55 finally
    56 {
    57 //rwl.ExitWriteLock();
    58 }
    59 }
    60
    61 public TValue GetObject(TKey key)
    62 {
    63 if (key == null)
    64 {
    65 throw new ArgumentNullException("key");
    66 }
    67
    68 TValue data = null;
    69 NodeInfo node;
    70 // rwl.EnterReadLock();
    71
    72 try
    73 {
    74 lock (key)
    75 {
    76 if (this.cachedNodesDictionary.TryGetValue(key, out node))
    77 {
    78 if (node != null)// && !node.IsExpired())
    79 {
    80 //Trace.WriteLine(string.Format("Cache hit for key: {0}", key.ToString()));
    81 node.AccessCount++;
    82 data = node.Value;
    83
    84 if (node.AccessCount > 20)
    85 {
    86 ThreadPool.QueueUserWorkItem(this.AddBeforeFirstNode, key);
    87 }
    88 }
    89 }
    90 else
    91 {
    92 // Trace.WriteLine(string.Format("Cache miss for key: {0}", key.ToString()));
    93 }
    94
    95 return data;
    96 }
    97 }
    98 finally
    99 {
    100 // rwl.ExitReadLock();
    101 }
    102 }
    103
    104 private void RemoveExpiredElements(object stateInfo)
    105 {
    106 // rwl.EnterWriteLock();
    107 try
    108 {
    109 lock (stateInfo)
    110 {
    111 while (this.lruLinkedList.Last != null)
    112 {
    113 NodeInfo node = this.lruLinkedList.Last.Value;
    114 if (node != null)// && node.IsExpired())
    115 {
    116 this.Delete(node);
    117 }
    118 else
    119 {
    120 break;
    121 }
    122 }
    123 }
    124 }
    125 finally
    126 {
    127 // rwl.ExitWriteLock();
    128 }
    129 }
    130
    131 private void CreateNodeandAddtoList(TKey userKey, TValue cacheObject)
    132 {
    133 NodeInfo node = new NodeInfo(userKey, cacheObject);//, (this.timeOut > DateTime.MaxValue.Subtract(DateTime.UtcNow) ? DateTime.MaxValue : DateTime.UtcNow.Add(this.timeOut)));
    134
    135 node.LLNode = this.lruLinkedList.AddFirst(node);
    136 this.cachedNodesDictionary[userKey] = node;
    137 }
    138
    139 private void AddBeforeFirstNode(object stateinfo)
    140 {
    141 //rwl.EnterWriteLock();
    142 try
    143 {
    144 lock (stateinfo)
    145 {
    146 TKey key = (TKey)stateinfo;
    147 NodeInfo nodeInfo;
    148 if (this.cachedNodesDictionary.TryGetValue(key, out nodeInfo))
    149 {
    150 if (nodeInfo != null && nodeInfo.AccessCount > 20)// && !nodeInfo.IsExpired()
    151 {
    152 if (nodeInfo.LLNode != this.lruLinkedList.First)
    153 {
    154 this.lruLinkedList.Remove(nodeInfo.LLNode);
    155 nodeInfo.LLNode = this.lruLinkedList.AddBefore(this.lruLinkedList.First, nodeInfo);
    156 nodeInfo.AccessCount = 0;
    157 }
    158 }
    159 }
    160 }
    161 }
    162 finally
    163 {
    164 // rwl.ExitWriteLock();
    165 }
    166 }
    167
    168 private void ShrinkToSize(int desiredSize)
    169 {
    170 while (this.cachedNodesDictionary.Count > desiredSize)
    171 {
    172 this.RemoveLeastValuableNode();
    173 }
    174 }
    175
    176 private void RemoveLeastValuableNode()
    177 {
    178 if (this.lruLinkedList.Last != null)
    179 {
    180 NodeInfo node = this.lruLinkedList.Last.Value;
    181 this.Delete(node);
    182 }
    183 }
    184
    185 private void Delete(NodeInfo node)
    186 {
    187 // Trace.WriteLine(string.Format("Evicting object from cache for key: {0}", node.Key.ToString()));
    188 this.lruLinkedList.Remove(node.LLNode);
    189 this.cachedNodesDictionary.Remove(node.Key);
    190 }
    191
    192 ////This class represents data stored in the LinkedList Node and Dictionary
    193 private class NodeInfo
    194 {
    195 //private readonly DateTime timeOutTime;
    196
    197 internal NodeInfo(TKey key, TValue value)//, DateTime timeouttime)
    198 {
    199 this.Key = key;
    200 this.Value = value;
    201 // this.timeOutTime = timeouttime;
    202 }
    203
    204 internal TKey Key { get; private set; }
    205
    206 internal TValue Value { get; private set; }
    207
    208 internal int AccessCount { get; set; }
    209
    210 internal LinkedListNode<NodeInfo> LLNode { get; set; }
    211
    212 //internal bool IsExpired()
    213 //{
    214 // return DateTime.UtcNow >= this.timeOutTime;
    215 //}
    216 }
    217 }
    218 }


    测试代码:

    1             LruCache<int, string> cache = new LruCache<int, string>(3, 1000);
    2 cache.AddObject(1, "One");
    3 cache.AddObject(2, "Two");
    4 cache.AddObject(3, "Three");
    5
    6 ////insert one more, which will kick 1 out
    7 cache.AddObject(4, "Four");
    8 Debug.WriteLine("cache.GetObject(1)" + cache.GetObject(1));
    9 Debug.WriteLine("cache.GetObject(4)===" + cache.GetObject(4));

    取图服务中应用流程:



  • 相关阅读:
    IIS处理Asp.net请求和 Asp.net页面生命周期
    帝国CMS实现一二级导航及其高亮
    dsoframer.ocx 遇到64为系统
    实现可编辑的表格
    delegate()
    当前页面高亮的方法!
    简单的js版tab
    js判断最大值
    解决chrome下的默认样式!
    纯js点击隐藏相邻节点
  • 原文地址:https://www.cnblogs.com/piaocz/p/2301817.html
Copyright © 2020-2023  润新知