http://git-wip-us.apache.org/repos/asf/lucenenet/blob/db375f93/src/contrib/Facet/Taxonomy/WriterCache/Lru/NameIntCacheLRU.cs ---------------------------------------------------------------------- diff --git a/src/contrib/Facet/Taxonomy/WriterCache/Lru/NameIntCacheLRU.cs b/src/contrib/Facet/Taxonomy/WriterCache/Lru/NameIntCacheLRU.cs new file mode 100644 index 0000000..a74fbfc --- /dev/null +++ b/src/contrib/Facet/Taxonomy/WriterCache/Lru/NameIntCacheLRU.cs @@ -0,0 +1,131 @@ +using Lucene.Net.Support; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Lucene.Net.Facet.Taxonomy.WriterCache.Lru +{ + public class NameIntCacheLRU + { + private HashMap<Object, int?> cache; + long nMisses = 0; + long nHits = 0; + private int maxCacheSize; + + internal NameIntCacheLRU(int maxCacheSize) + { + this.maxCacheSize = maxCacheSize; + CreateCache(maxCacheSize); + } + + public virtual int MaxSize + { + get + { + return maxCacheSize; + } + } + + public virtual int Size + { + get + { + return cache.Count; + } + } + + private void CreateCache(int maxSize) + { + cache = new HashMap<object, int?>(1000); + //if (maxSize < int.MaxValue) + //{ + // cache = new HashMap<Object, int?>(1000, (float)0.7, true); + //} + //else + //{ + // cache = new HashMap<Object, int?>(1000, (float)0.7); + //} + } + + internal virtual int? Get(CategoryPath name) + { + int? res = cache[Key(name)]; + if (res == null) + { + nMisses++; + } + else + { + nHits++; + } + + return res; + } + + internal virtual Object Key(CategoryPath name) + { + return name; + } + + internal virtual Object Key(CategoryPath name, int prefixLen) + { + return name.Subpath(prefixLen); + } + + internal virtual bool Put(CategoryPath name, int? val) + { + cache[Key(name)] = val; + return IsCacheFull; + } + + internal virtual bool Put(CategoryPath name, int prefixLen, int? val) + { + cache[Key(name, prefixLen)] = val; + return IsCacheFull; + } + + private bool IsCacheFull + { + get + { + return cache.Count > maxCacheSize; + } + } + + internal virtual void Clear() + { + cache.Clear(); + } + + internal virtual string Stats() + { + return @"#miss=" + nMisses + @" #hit=" + nHits; + } + + internal virtual bool MakeRoomLRU() + { + if (!IsCacheFull) + { + return false; + } + + int n = cache.Count - (2 * maxCacheSize) / 3; + if (n <= 0) + { + return false; + } + + IEnumerator<Object> it = new HashSet<object>(cache.Keys).GetEnumerator(); + int i = 0; + while (i < n && it.MoveNext()) + { + //it.Current; + cache.Remove(it.Current); + i++; + } + + return true; + } + } +}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/db375f93/src/core/Lucene.Net.csproj ---------------------------------------------------------------------- diff --git a/src/core/Lucene.Net.csproj b/src/core/Lucene.Net.csproj index 47b4cd3..47713a1 100644 --- a/src/core/Lucene.Net.csproj +++ b/src/core/Lucene.Net.csproj @@ -911,9 +911,11 @@ <Compile Include="Support\IdentityHashMap.cs" /> <Compile Include="Support\IdentityHashSet.cs" /> <Compile Include="Support\IdentityWeakReferenceT.cs" /> + <Compile Include="Support\IndexedLinkedList.cs" /> <Compile Include="Support\Inflater.cs" /> <Compile Include="Support\IThreadRunnable.cs" /> <Compile Include="Support\ListExtensions.cs" /> + <Compile Include="Support\LRUCache.cs" /> <Compile Include="Support\MemoryMappedFileByteBuffer.cs" /> <Compile Include="Support\Number.cs" /> <Compile Include="Support\NumberExtensions.cs" /> http://git-wip-us.apache.org/repos/asf/lucenenet/blob/db375f93/src/core/Support/IndexedLinkedList.cs ---------------------------------------------------------------------- diff --git a/src/core/Support/IndexedLinkedList.cs b/src/core/Support/IndexedLinkedList.cs new file mode 100644 index 0000000..6f0855d --- /dev/null +++ b/src/core/Support/IndexedLinkedList.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Lucene.Net.Support +{ + public class IndexedLinkedList<T> + { + LinkedList<T> data = new LinkedList<T>(); + Dictionary<T, LinkedListNode<T>> index = new Dictionary<T, LinkedListNode<T>>(); + + public void Add(T value) + { + index[value] = data.AddLast(value); + } + + public void RemoveFirst() + { + index.Remove(data.First.Value); + data.RemoveFirst(); + } + + public void Remove(T value) + { + LinkedListNode<T> node; + if (index.TryGetValue(value, out node)) + { + data.Remove(node); + index.Remove(value); + } + } + + public int Count + { + get + { + return data.Count; + } + } + + public void Clear() + { + data.Clear(); + index.Clear(); + } + + public T First + { + get + { + return data.First.Value; + } + } + } +} http://git-wip-us.apache.org/repos/asf/lucenenet/blob/db375f93/src/core/Support/LRUCache.cs ---------------------------------------------------------------------- diff --git a/src/core/Support/LRUCache.cs b/src/core/Support/LRUCache.cs new file mode 100644 index 0000000..52d9cd1 --- /dev/null +++ b/src/core/Support/LRUCache.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Lucene.Net.Support +{ + public class LRUCache<TKey, TValue> : IDictionary<TKey, TValue> + { + object sync = new object(); + Dictionary<TKey, TValue> data; + IndexedLinkedList<TKey> lruList = new IndexedLinkedList<TKey>(); + ICollection<KeyValuePair<TKey, TValue>> dataAsCollection; + int capacity; + + public LRUCache(int capacity) + { + + if (capacity <= 0) + { + throw new ArgumentException("capacity should always be bigger than 0"); + } + + data = new Dictionary<TKey, TValue>(capacity); + dataAsCollection = data; + this.capacity = capacity; + } + + public void Add(TKey key, TValue value) + { + if (!ContainsKey(key)) + { + this[key] = value; + } + else + { + throw new ArgumentException("An attempt was made to insert a duplicate key in the cache."); + } + } + + public bool ContainsKey(TKey key) + { + return data.ContainsKey(key); + } + + public ICollection<TKey> Keys + { + get + { + return data.Keys; + } + } + + public bool Remove(TKey key) + { + bool existed = data.Remove(key); + lruList.Remove(key); + return existed; + } + + public bool TryGetValue(TKey key, out TValue value) + { + return data.TryGetValue(key, out value); + } + + public ICollection<TValue> Values + { + get { return data.Values; } + } + + public TValue this[TKey key] + { + get + { + var value = data[key]; + lruList.Remove(key); + lruList.Add(key); + return value; + } + set + { + data[key] = value; + lruList.Remove(key); + lruList.Add(key); + + if (data.Count > capacity) + { + data.Remove(lruList.First); + lruList.RemoveFirst(); + } + } + } + + public void Add(KeyValuePair<TKey, TValue> item) + { + Add(item.Key, item.Value); + } + + public void Clear() + { + data.Clear(); + lruList.Clear(); + } + + public bool Contains(KeyValuePair<TKey, TValue> item) + { + return dataAsCollection.Contains(item); + } + + public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) + { + dataAsCollection.CopyTo(array, arrayIndex); + } + + public int Count + { + get { return data.Count; } + } + + public bool IsReadOnly + { + get { return false; } + } + + public bool Remove(KeyValuePair<TKey, TValue> item) + { + + bool removed = dataAsCollection.Remove(item); + if (removed) + { + lruList.Remove(item.Key); + } + return removed; + } + + + public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() + { + return dataAsCollection.GetEnumerator(); + } + + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return ((System.Collections.IEnumerable)data).GetEnumerator(); + } + + public int Capacity + { + get { return capacity; } + set + { + capacity = value; + } + } + } +}
