Skip to content

Commit

Permalink
Part-1 Neo.IO - move (#3387)
Browse files Browse the repository at this point in the history
Co-authored-by: Shargon <shargon@gmail.com>
Co-authored-by: NGD Admin <154295625+NGDAdmin@users.noreply.github.com>
  • Loading branch information
3 people committed Jul 5, 2024
1 parent 8e1e661 commit 15d36b7
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 81 deletions.
56 changes: 23 additions & 33 deletions src/Neo/IO/Caching/Cache.cs → src/Neo.IO/Caching/Cache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,21 @@

namespace Neo.IO.Caching
{
internal abstract class Cache<TKey, TValue> : ICollection<TValue>, IDisposable
internal abstract class Cache<TKey, TValue>
(int max_capacity, IEqualityComparer<TKey>? comparer = null) : ICollection<TValue>, IDisposable
where TKey : notnull
{
protected class CacheItem
(TKey key, TValue value)
{
public readonly TKey Key;
public readonly TValue Value;
public readonly DateTime Time;

public CacheItem(TKey key, TValue value)
{
Key = key;
Value = value;
Time = TimeProvider.Current.UtcNow;
}
public readonly TKey Key = key;
public readonly TValue Value = value;
public readonly DateTime Time = DateTime.UtcNow;
}

protected readonly ReaderWriterLockSlim RwSyncRootLock = new(LockRecursionPolicy.SupportsRecursion);
protected readonly Dictionary<TKey, CacheItem> InnerDictionary;
private readonly int max_capacity;
protected readonly Dictionary<TKey, CacheItem> InnerDictionary = new Dictionary<TKey, CacheItem>(comparer);
private readonly int _max_capacity = max_capacity;

public TValue this[TKey key]
{
Expand All @@ -44,7 +40,7 @@ public TValue this[TKey key]
RwSyncRootLock.EnterReadLock();
try
{
if (!InnerDictionary.TryGetValue(key, out CacheItem item)) throw new KeyNotFoundException();
if (!InnerDictionary.TryGetValue(key, out CacheItem? item)) throw new KeyNotFoundException();
OnAccess(item);
return item.Value;
}
Expand Down Expand Up @@ -73,15 +69,9 @@ public int Count

public bool IsReadOnly => false;

public Cache(int max_capacity, IEqualityComparer<TKey> comparer = null)
{
this.max_capacity = max_capacity;
InnerDictionary = new Dictionary<TKey, CacheItem>(comparer);
}

public void Add(TValue item)
{
TKey key = GetKeyForItem(item);
var key = GetKeyForItem(item);
RwSyncRootLock.EnterWriteLock();
try
{
Expand All @@ -95,16 +85,16 @@ public void Add(TValue item)

private void AddInternal(TKey key, TValue item)
{
if (InnerDictionary.TryGetValue(key, out CacheItem cacheItem))
if (InnerDictionary.TryGetValue(key, out CacheItem? cacheItem))
{
OnAccess(cacheItem);
}
else
{
if (InnerDictionary.Count >= max_capacity)
if (InnerDictionary.Count >= _max_capacity)
{
//TODO: Perform a performance test on the PLINQ query to determine which algorithm is better here (parallel or not)
foreach (CacheItem item_del in InnerDictionary.Values.AsParallel().OrderBy(p => p.Time).Take(InnerDictionary.Count - max_capacity + 1))
foreach (var item_del in InnerDictionary.Values.AsParallel().OrderBy(p => p.Time).Take(InnerDictionary.Count - _max_capacity + 1))
{
RemoveInternal(item_del);
}
Expand All @@ -118,9 +108,9 @@ public void AddRange(IEnumerable<TValue> items)
RwSyncRootLock.EnterWriteLock();
try
{
foreach (TValue item in items)
foreach (var item in items)
{
TKey key = GetKeyForItem(item);
var key = GetKeyForItem(item);
AddInternal(key, item);
}
}
Expand All @@ -135,7 +125,7 @@ public void Clear()
RwSyncRootLock.EnterWriteLock();
try
{
foreach (CacheItem item_del in InnerDictionary.Values.ToArray())
foreach (var item_del in InnerDictionary.Values.ToArray())
{
RemoveInternal(item_del);
}
Expand All @@ -151,7 +141,7 @@ public bool Contains(TKey key)
RwSyncRootLock.EnterReadLock();
try
{
if (!InnerDictionary.TryGetValue(key, out CacheItem cacheItem)) return false;
if (!InnerDictionary.TryGetValue(key, out CacheItem? cacheItem)) return false;
OnAccess(cacheItem);
return true;
}
Expand All @@ -171,7 +161,7 @@ public void CopyTo(TValue[] array, int arrayIndex)
if (array == null) throw new ArgumentNullException();
if (arrayIndex < 0) throw new ArgumentOutOfRangeException();
if (arrayIndex + InnerDictionary.Count > array.Length) throw new ArgumentException();
foreach (TValue item in this)
foreach (var item in this)
{
array[arrayIndex++] = item;
}
Expand All @@ -188,7 +178,7 @@ public IEnumerator<TValue> GetEnumerator()
RwSyncRootLock.EnterReadLock();
try
{
foreach (TValue item in InnerDictionary.Values.Select(p => p.Value))
foreach (var item in InnerDictionary.Values.Select(p => p.Value))
{
yield return item;
}
Expand All @@ -211,7 +201,7 @@ public bool Remove(TKey key)
RwSyncRootLock.EnterWriteLock();
try
{
if (!InnerDictionary.TryGetValue(key, out CacheItem cacheItem)) return false;
if (!InnerDictionary.TryGetValue(key, out CacheItem? cacheItem)) return false;
RemoveInternal(cacheItem);
return true;
}
Expand Down Expand Up @@ -242,7 +232,7 @@ public bool TryGet(TKey key, out TValue item)
RwSyncRootLock.EnterReadLock();
try
{
if (InnerDictionary.TryGetValue(key, out CacheItem cacheItem))
if (InnerDictionary.TryGetValue(key, out CacheItem? cacheItem))
{
OnAccess(cacheItem);
item = cacheItem.Value;
Expand All @@ -253,7 +243,7 @@ public bool TryGet(TKey key, out TValue item)
{
RwSyncRootLock.ExitReadLock();
}
item = default;
item = default!;
return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,10 @@

namespace Neo.IO.Caching
{
internal abstract class FIFOCache<TKey, TValue> : Cache<TKey, TValue>
internal abstract class FIFOCache<TKey, TValue>
(int max_capacity, IEqualityComparer<TKey>? comparer = null) : Cache<TKey, TValue>(max_capacity, comparer)
where TKey : notnull
{
public FIFOCache(int max_capacity, IEqualityComparer<TKey> comparer = null)
: base(max_capacity, comparer)
{
}

protected override void OnAccess(CacheItem item)
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ class HashSetCache<T> : IReadOnlyCollection<T> where T : IEquatable<T>
/// <summary>
/// Sets where the Hashes are stored
/// </summary>
private readonly LinkedList<HashSet<T>> sets = new();
private readonly LinkedList<HashSet<T>> _sets = new();

/// <summary>
/// Maximum capacity of each bucket inside each HashSet of <see cref="sets"/>.
/// Maximum capacity of each bucket inside each HashSet of <see cref="_sets"/>.
/// </summary>
private readonly int bucketCapacity;
private readonly int _bucketCapacity;

/// <summary>
/// Maximum number of buckets for the LinkedList, meaning its maximum cardinality.
/// </summary>
private readonly int maxBucketCount;
private readonly int _maxBucketCount;

/// <summary>
/// Entry count
Expand All @@ -43,32 +43,32 @@ public HashSetCache(int bucketCapacity, int maxBucketCount = 10)
if (maxBucketCount <= 0) throw new ArgumentOutOfRangeException($"{nameof(maxBucketCount)} should be greater than 0");

Count = 0;
this.bucketCapacity = bucketCapacity;
this.maxBucketCount = maxBucketCount;
sets.AddFirst(new HashSet<T>());
_bucketCapacity = bucketCapacity;
_maxBucketCount = maxBucketCount;
_sets.AddFirst([]);
}

public bool Add(T item)
{
if (Contains(item)) return false;
Count++;
if (sets.First.Value.Count < bucketCapacity) return sets.First.Value.Add(item);
if (_sets.First?.Value.Count < _bucketCapacity) return _sets.First.Value.Add(item);
var newSet = new HashSet<T>
{
item
};
sets.AddFirst(newSet);
if (sets.Count > maxBucketCount)
_sets.AddFirst(newSet);
if (_sets.Count > _maxBucketCount)
{
Count -= sets.Last.Value.Count;
sets.RemoveLast();
Count -= _sets.Last?.Value.Count ?? 0;
_sets.RemoveLast();
}
return true;
}

public bool Contains(T item)
{
foreach (var set in sets)
foreach (var set in _sets)
{
if (set.Contains(item)) return true;
}
Expand All @@ -77,17 +77,17 @@ public bool Contains(T item)

public void ExceptWith(IEnumerable<T> items)
{
List<HashSet<T>> removeList = null;
List<HashSet<T>> removeList = default!;
foreach (var item in items)
{
foreach (var set in sets)
foreach (var set in _sets)
{
if (set.Remove(item))
{
Count--;
if (set.Count == 0)
{
removeList ??= new List<HashSet<T>>();
removeList ??= [];
removeList.Add(set);
}
break;
Expand All @@ -97,13 +97,13 @@ public void ExceptWith(IEnumerable<T> items)
if (removeList == null) return;
foreach (var set in removeList)
{
sets.Remove(set);
_sets.Remove(set);
}
}

public IEnumerator<T> GetEnumerator()
{
foreach (var set in sets)
foreach (var set in _sets)
{
foreach (var item in set)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,14 @@ public void Enqueue(T item)
{
if (_array.Length == _count)
{
int newSize = _array.Length * GrowthFactor;
var newSize = _array.Length * GrowthFactor;
if (_head == 0)
{
Array.Resize(ref _array, newSize);
}
else
{
T[] buffer = new T[newSize];
var buffer = new T[newSize];
Array.Copy(_array, _head, buffer, 0, _array.Length - _head);
Array.Copy(_array, 0, buffer, _array.Length - _head, _head);
_array = buffer;
Expand Down Expand Up @@ -127,7 +127,7 @@ public bool TryPeek(out T item)
{
if (_count == 0)
{
item = default;
item = default!;
return false;
}
else
Expand All @@ -145,7 +145,7 @@ public T Dequeue()
{
if (_count == 0)
throw new InvalidOperationException("The queue is empty");
T result = _array[_head];
var result = _array[_head];
++_head;
_head %= _array.Length;
--_count;
Expand All @@ -161,7 +161,7 @@ public bool TryDequeue(out T item)
{
if (_count == 0)
{
item = default;
item = default!;
return false;
}
else
Expand Down Expand Up @@ -194,7 +194,7 @@ public void TrimExcess()
}
else if (_array.Length * TrimThreshold >= _count)
{
T[] arr = new T[_count];
var arr = new T[_count];
CopyTo(arr, 0);
_array = arr;
_head = 0;
Expand Down Expand Up @@ -228,14 +228,14 @@ public void CopyTo(T[] array, int arrayIndex)
/// <returns>An array containing the queue's items</returns>
public T[] ToArray()
{
T[] result = new T[_count];
var result = new T[_count];
CopyTo(result, 0);
return result;
}

public IEnumerator<T> GetEnumerator()
{
for (int i = 0; i < _count; i++)
for (var i = 0; i < _count; i++)
yield return _array[(_head + i) % _array.Length];
}

Expand Down
Loading

0 comments on commit 15d36b7

Please sign in to comment.