aboutsummaryrefslogtreecommitdiff
path: root/lib/Utils/src
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2023-01-27 21:13:05 -0500
committerLibravatar vnugent <public@vaughnnugent.com>2023-01-27 21:13:05 -0500
commita5d88f2cf08ea3aad2c8802bdc416e7b40c0f204 (patch)
treee7b9347717c096ef0ea517769b5136ef8abf9571 /lib/Utils/src
parent185afcee727027c60257ddda4da974dccb808e5a (diff)
Object cache overhaul and logger updates
Diffstat (limited to 'lib/Utils/src')
-rw-r--r--lib/Utils/src/Logging/ILogProvider.cs8
-rw-r--r--lib/Utils/src/Memory/Caching/LRUCache.cs13
-rw-r--r--lib/Utils/src/Memory/Caching/LRUDataStore.cs43
-rw-r--r--lib/Utils/src/Memory/MemoryHandle.cs2
-rw-r--r--lib/Utils/src/Memory/MemoryUtil.cs33
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.