From a5d88f2cf08ea3aad2c8802bdc416e7b40c0f204 Mon Sep 17 00:00:00 2001 From: vnugent Date: Fri, 27 Jan 2023 21:13:05 -0500 Subject: Object cache overhaul and logger updates --- lib/Utils/src/Logging/ILogProvider.cs | 8 ++++++ lib/Utils/src/Memory/Caching/LRUCache.cs | 13 +++++---- lib/Utils/src/Memory/Caching/LRUDataStore.cs | 43 +++++++++++++++++++++------- lib/Utils/src/Memory/MemoryHandle.cs | 2 +- lib/Utils/src/Memory/MemoryUtil.cs | 33 +++++++++++++++++++++ 5 files changed, 82 insertions(+), 17 deletions(-) (limited to 'lib/Utils/src') 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 /// /// The underlying log source object GetLogProvider(); + + /// + /// Checks if the desired log level is enabled. + /// + /// The log level to check + /// True if the log level is available to write logs to, false if the level is not available to write to + bool IsEnabled(LogLevel level); + /// /// Gets the underlying log source /// 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 /// /// A to add to the cache store - public override void Add(KeyValuePair item) + public override void Add(in KeyValuePair 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> 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 oldRecord = oldNode.Value; + ref KeyValuePair 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); } } + /// /// Attempts to get a value by the given key. /// @@ -115,7 +116,7 @@ namespace VNLib.Utils.Memory.Caching /// Invoked when a record is evicted from the cache /// /// The record that is being evicted - protected abstract void Evicted(KeyValuePair evicted); + protected abstract void Evicted(ref KeyValuePair evicted); /// /// Invoked when an entry was requested and was not found in cache. /// 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>> LookupTable { get; } /// /// 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 /// protected LinkedList> List { get; } @@ -57,6 +57,7 @@ namespace VNLib.Utils.Memory.Caching LookupTable = new(); List = new(); } + /// /// Initializes an empty and sets /// the lookup table's inital capacity @@ -67,6 +68,7 @@ namespace VNLib.Utils.Memory.Caching LookupTable = new(initialCapacity); List = new(); } + /// /// Initializes an empty and uses the /// specified keycomparison @@ -77,6 +79,7 @@ namespace VNLib.Utils.Memory.Caching LookupTable = new(keyComparer); List = new(); } + /// /// Initializes an empty 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(key, value); - //Move the item to the front of the list + + //Reuse the node + oldNode.ValueRef = new KeyValuePair(key, value); + + //Move the item to the back of the list List.AddLast(oldNode); } else @@ -123,9 +129,12 @@ namespace VNLib.Utils.Memory.Caching } /// public ICollection Keys => LookupTable.Keys; - /// + + /// + /// Not supported + /// /// - public ICollection Values => throw new NotImplementedException(); + public virtual ICollection Values => throw new NotSupportedException("Values are not stored in an independent collection, as they are not directly mutable"); IEnumerable IReadOnlyDictionary.Keys => LookupTable.Keys; IEnumerable IReadOnlyDictionary.Values => List.Select(static node => node.Value); IEnumerator IEnumerable.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 /// public int Count => List.Count; + /// public abstract bool IsReadOnly { get; } @@ -147,10 +157,11 @@ namespace VNLib.Utils.Memory.Caching //Create new kvp lookup ref KeyValuePair lookupRef = new(key, value); //Insert the lookup - Add(lookupRef); + Add(in lookupRef); } + /// - public bool Remove(KeyValuePair item) => Remove(item.Key); + public bool Remove(in KeyValuePair item) => Remove(item.Key); /// IEnumerator IEnumerable.GetEnumerator() => List.GetEnumerator(); /// @@ -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 /// /// The item to add - public virtual void Add(KeyValuePair item) + public virtual void Add(in KeyValuePair item) { //Init new ll node LinkedListNode> newNode = new(item); @@ -173,6 +184,7 @@ namespace VNLib.Utils.Memory.Caching //Add to the end of the linked list List.AddLast(newNode); } + /// /// Removes all elements from the LRU store /// @@ -187,7 +199,7 @@ namespace VNLib.Utils.Memory.Caching /// /// The record to search for /// True if the key was found in the store and the value equals the stored value, false otherwise - public virtual bool Contains(KeyValuePair item) + public virtual bool Contains(in KeyValuePair item) { if (LookupTable.TryGetValue(item.Key, out LinkedListNode>? lookup)) { @@ -227,6 +239,17 @@ namespace VNLib.Utils.Memory.Caching value = default; return false; } - + + /// + /// Adds the specified record to the store and places it at the end of the LRU queue + /// + /// The item to add + public virtual void Add(KeyValuePair item) => Add(in item); + + /// + public virtual bool Contains(KeyValuePair item) => Contains(in item); + + /// + public bool Remove(KeyValuePair 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 /// /// - 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 + + /// + /// Rounds the requested byte size up to the nearest page + /// number of bytes + /// + /// The number of bytes to get the rounded page size of + /// The number of bytes equivalent to the requested byte size rounded to the next system memory page + [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; + } + + /// + /// Rounds the requested byte size up to the nearest page + /// number of bytes + /// + /// The number of bytes to get the rounded page size of + /// The number of bytes equivalent to the requested byte size rounded to the next system memory page + [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; + } + /// /// Allocates a block of unmanaged, or pooled manaaged memory depending on /// compilation flags and runtime unamanged allocators. -- cgit