diff options
author | vnugent <public@vaughnnugent.com> | 2023-01-27 21:13:05 -0500 |
---|---|---|
committer | vnugent <public@vaughnnugent.com> | 2023-01-27 21:13:05 -0500 |
commit | a5d88f2cf08ea3aad2c8802bdc416e7b40c0f204 (patch) | |
tree | e7b9347717c096ef0ea517769b5136ef8abf9571 /lib/Utils/src | |
parent | 185afcee727027c60257ddda4da974dccb808e5a (diff) |
Object cache overhaul and logger updates
Diffstat (limited to 'lib/Utils/src')
-rw-r--r-- | lib/Utils/src/Logging/ILogProvider.cs | 8 | ||||
-rw-r--r-- | lib/Utils/src/Memory/Caching/LRUCache.cs | 13 | ||||
-rw-r--r-- | lib/Utils/src/Memory/Caching/LRUDataStore.cs | 43 | ||||
-rw-r--r-- | lib/Utils/src/Memory/MemoryHandle.cs | 2 | ||||
-rw-r--r-- | lib/Utils/src/Memory/MemoryUtil.cs | 33 |
5 files changed, 82 insertions, 17 deletions
diff --git a/lib/Utils/src/Logging/ILogProvider.cs b/lib/Utils/src/Logging/ILogProvider.cs index 55dbd6f..3fce8b6 100644 --- a/lib/Utils/src/Logging/ILogProvider.cs +++ b/lib/Utils/src/Logging/ILogProvider.cs @@ -70,6 +70,14 @@ namespace VNLib.Utils.Logging /// </summary> /// <returns>The underlying log source</returns> object GetLogProvider(); + + /// <summary> + /// Checks if the desired log level is enabled. + /// </summary> + /// <param name="level">The log level to check</param> + /// <returns>True if the log level is available to write logs to, false if the level is not available to write to</returns> + bool IsEnabled(LogLevel level); + /// <summary> /// Gets the underlying log source /// </summary> diff --git a/lib/Utils/src/Memory/Caching/LRUCache.cs b/lib/Utils/src/Memory/Caching/LRUCache.cs index 7e96e0a..6cbb425 100644 --- a/lib/Utils/src/Memory/Caching/LRUCache.cs +++ b/lib/Utils/src/Memory/Caching/LRUCache.cs @@ -56,17 +56,17 @@ namespace VNLib.Utils.Memory.Caching /// Adds a new record to the LRU cache /// </summary> /// <param name="item">A <see cref="KeyValuePair{TKey, TValue}"/> to add to the cache store</param> - public override void Add(KeyValuePair<TKey, TValue> item) + public override void Add(in KeyValuePair<TKey, TValue> item) { //See if the store is at max capacity and an item needs to be evicted - if(Count == MaxCapacity) + if (Count == MaxCapacity) { //A record needs to be evicted before a new record can be added //Get the oldest node from the list to reuse its instance and remove the old value LinkedListNode<KeyValuePair<TKey, TValue>> oldNode = List.First!; //not null because count is at max capacity so an item must be at the end of the list //Store old node value field - KeyValuePair<TKey, TValue> oldRecord = oldNode.Value; + ref KeyValuePair<TKey, TValue> oldRecord = ref oldNode.ValueRef; //Remove from lookup LookupTable.Remove(oldRecord.Key); //Remove the node @@ -78,14 +78,15 @@ namespace VNLib.Utils.Memory.Caching //Add to end of list List.AddLast(oldNode); //Invoke evicted method - Evicted(oldRecord); + Evicted(ref oldRecord); } else { //Add new item to the list - base.Add(item); + base.Add(in item); } } + /// <summary> /// Attempts to get a value by the given key. /// </summary> @@ -115,7 +116,7 @@ namespace VNLib.Utils.Memory.Caching /// Invoked when a record is evicted from the cache /// </summary> /// <param name="evicted">The record that is being evicted</param> - protected abstract void Evicted(KeyValuePair<TKey, TValue> evicted); + protected abstract void Evicted(ref KeyValuePair<TKey, TValue> evicted); /// <summary> /// Invoked when an entry was requested and was not found in cache. /// </summary> diff --git a/lib/Utils/src/Memory/Caching/LRUDataStore.cs b/lib/Utils/src/Memory/Caching/LRUDataStore.cs index f564fcc..89d7c12 100644 --- a/lib/Utils/src/Memory/Caching/LRUDataStore.cs +++ b/lib/Utils/src/Memory/Caching/LRUDataStore.cs @@ -44,7 +44,7 @@ namespace VNLib.Utils.Memory.Caching protected Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> LookupTable { get; } /// <summary> /// A linked list that tracks the least recently used item. - /// New items (or recently access items) are moved to the end of the list. + /// New items (or recently accessed items) are moved to the end of the list. /// The head contains the least recently used item /// </summary> protected LinkedList<KeyValuePair<TKey, TValue>> List { get; } @@ -57,6 +57,7 @@ namespace VNLib.Utils.Memory.Caching LookupTable = new(); List = new(); } + /// <summary> /// Initializes an empty <see cref="LRUDataStore{TKey, TValue}"/> and sets /// the lookup table's inital capacity @@ -67,6 +68,7 @@ namespace VNLib.Utils.Memory.Caching LookupTable = new(initialCapacity); List = new(); } + /// <summary> /// Initializes an empty <see cref="LRUDataStore{TKey, TValue}"/> and uses the /// specified keycomparison @@ -77,6 +79,7 @@ namespace VNLib.Utils.Memory.Caching LookupTable = new(keyComparer); List = new(); } + /// <summary> /// Initializes an empty <see cref="LRUDataStore{TKey, TValue}"/> and uses the /// specified keycomparison, and sets the lookup table's initial capacity @@ -110,8 +113,11 @@ namespace VNLib.Utils.Memory.Caching { //Remove the node before re-adding it List.Remove(oldNode); - oldNode.Value = new KeyValuePair<TKey, TValue>(key, value); - //Move the item to the front of the list + + //Reuse the node + oldNode.ValueRef = new KeyValuePair<TKey, TValue>(key, value); + + //Move the item to the back of the list List.AddLast(oldNode); } else @@ -123,9 +129,12 @@ namespace VNLib.Utils.Memory.Caching } ///<inheritdoc/> public ICollection<TKey> Keys => LookupTable.Keys; - ///<inheritdoc/> + + ///<summary> + /// Not supported + /// </summary> ///<exception cref="NotImplementedException"></exception> - public ICollection<TValue> Values => throw new NotImplementedException(); + public virtual ICollection<TValue> Values => throw new NotSupportedException("Values are not stored in an independent collection, as they are not directly mutable"); IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys => LookupTable.Keys; IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => List.Select(static node => node.Value); IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() => List.Select(static node => node.Value).GetEnumerator(); @@ -134,6 +143,7 @@ namespace VNLib.Utils.Memory.Caching /// Gets the number of items within the LRU store /// </summary> public int Count => List.Count; + ///<inheritdoc/> public abstract bool IsReadOnly { get; } @@ -147,10 +157,11 @@ namespace VNLib.Utils.Memory.Caching //Create new kvp lookup ref KeyValuePair<TKey, TValue> lookupRef = new(key, value); //Insert the lookup - Add(lookupRef); + Add(in lookupRef); } + ///<inheritdoc/> - public bool Remove(KeyValuePair<TKey, TValue> item) => Remove(item.Key); + public bool Remove(in KeyValuePair<TKey, TValue> item) => Remove(item.Key); ///<inheritdoc/> IEnumerator IEnumerable.GetEnumerator() => List.GetEnumerator(); ///<inheritdoc/> @@ -164,7 +175,7 @@ namespace VNLib.Utils.Memory.Caching /// Adds the specified record to the store and places it at the end of the LRU queue /// </summary> /// <param name="item">The item to add</param> - public virtual void Add(KeyValuePair<TKey, TValue> item) + public virtual void Add(in KeyValuePair<TKey, TValue> item) { //Init new ll node LinkedListNode<KeyValuePair<TKey, TValue>> newNode = new(item); @@ -173,6 +184,7 @@ namespace VNLib.Utils.Memory.Caching //Add to the end of the linked list List.AddLast(newNode); } + /// <summary> /// Removes all elements from the LRU store /// </summary> @@ -187,7 +199,7 @@ namespace VNLib.Utils.Memory.Caching /// </summary> /// <param name="item">The record to search for</param> /// <returns>True if the key was found in the store and the value equals the stored value, false otherwise</returns> - public virtual bool Contains(KeyValuePair<TKey, TValue> item) + public virtual bool Contains(in KeyValuePair<TKey, TValue> item) { if (LookupTable.TryGetValue(item.Key, out LinkedListNode<KeyValuePair<TKey, TValue>>? lookup)) { @@ -227,6 +239,17 @@ namespace VNLib.Utils.Memory.Caching value = default; return false; } - + + /// <summary> + /// Adds the specified record to the store and places it at the end of the LRU queue + /// </summary> + /// <param name="item">The item to add</param> + public virtual void Add(KeyValuePair<TKey, TValue> item) => Add(in item); + + ///<inheritdoc/> + public virtual bool Contains(KeyValuePair<TKey, TValue> item) => Contains(in item); + + ///<inheritdoc/> + public bool Remove(KeyValuePair<TKey, TValue> item) => Remove(in item); } } diff --git a/lib/Utils/src/Memory/MemoryHandle.cs b/lib/Utils/src/Memory/MemoryHandle.cs index df2792b..7a6b4ef 100644 --- a/lib/Utils/src/Memory/MemoryHandle.cs +++ b/lib/Utils/src/Memory/MemoryHandle.cs @@ -92,7 +92,7 @@ namespace VNLib.Utils.Memory /// Number of bytes allocated to the current instance /// </summary> /// <exception cref="OverflowException"></exception> - public unsafe ulong ByteLength + public nuint ByteLength { //Check for overflows when converting to bytes (should run out of memory before this is an issue, but just incase) [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/lib/Utils/src/Memory/MemoryUtil.cs b/lib/Utils/src/Memory/MemoryUtil.cs index 56ccb7e..2d51d2f 100644 --- a/lib/Utils/src/Memory/MemoryUtil.cs +++ b/lib/Utils/src/Memory/MemoryUtil.cs @@ -588,6 +588,39 @@ namespace VNLib.Utils.Memory #region alloc + + /// <summary> + /// Rounds the requested byte size up to the nearest page + /// number of bytes + /// </summary> + /// <param name="byteSize">The number of bytes to get the rounded page size of</param> + /// <returns>The number of bytes equivalent to the requested byte size rounded to the next system memory page</returns> + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nuint NearestPage(nuint byteSize) + { + //Get page count by dividing count by number of pages + nuint pages = (uint)Math.Ceiling(byteSize / (double)Environment.SystemPageSize); + + //Multiply back to page sizes + return pages * (nuint)Environment.SystemPageSize; + } + + /// <summary> + /// Rounds the requested byte size up to the nearest page + /// number of bytes + /// </summary> + /// <param name="byteSize">The number of bytes to get the rounded page size of</param> + /// <returns>The number of bytes equivalent to the requested byte size rounded to the next system memory page</returns> + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint NearestPage(nint byteSize) + { + //Get page count by dividing count by number of pages + nint pages = (int)Math.Ceiling(byteSize / (double)Environment.SystemPageSize); + + //Multiply back to page sizes + return pages * Environment.SystemPageSize; + } + /// <summary> /// Allocates a block of unmanaged, or pooled manaaged memory depending on /// compilation flags and runtime unamanged allocators. |