aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2024-02-29 21:22:38 -0500
committerLibravatar vnugent <public@vaughnnugent.com>2024-02-29 21:22:38 -0500
commit016a96a80cce025a86c6cf26707738f6a2eb2658 (patch)
tree2648ea3f111493253c2c7bd635784daab393f609
parent456ead9bc8b0f61357bae93152ad0403c4940101 (diff)
feat: add future support for memory diagnostics, and some docs
-rw-r--r--Taskfile.yaml5
-rw-r--r--lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheTable.cs15
-rw-r--r--lib/VNLib.Data.Caching.ObjectCache/src/ICacheEntryMemoryManager.cs8
-rw-r--r--plugins/ObjectCacheServer/src/BucketLocalManagerFactory.cs52
-rw-r--r--plugins/ObjectCacheServer/src/Cache/CacheStore.cs11
5 files changed, 55 insertions, 36 deletions
diff --git a/Taskfile.yaml b/Taskfile.yaml
index bb95e21..48aef59 100644
--- a/Taskfile.yaml
+++ b/Taskfile.yaml
@@ -68,7 +68,6 @@ tasks:
clean:
dir: '{{.USER_WORKING_DIR}}'
cmds:
- - cmd: powershell Remove-Item -Recurse './bin'
- ignore_error: true
- - cmd: powershell Remove-Item -Recurse './obj'
+ - for: ['./bin', './obj']
+ cmd: powershell Remove-Item -Recurse '{{.ITEM}}'
ignore_error: true
diff --git a/lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheTable.cs b/lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheTable.cs
index 8270f2f..789448d 100644
--- a/lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheTable.cs
+++ b/lib/VNLib.Data.Caching.ObjectCache/src/BlobCacheTable.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Data.Caching.ObjectCache
@@ -66,12 +66,8 @@ namespace VNLib.Data.Caching.ObjectCache
/// <exception cref="ArgumentException"></exception>
public BlobCacheTable(uint tableSize, uint bucketSize, ICacheMemoryManagerFactory factory, IPersistantCacheStore? persistantCache)
{
- _ = factory ?? throw new ArgumentNullException(nameof(factory));
-
- if(tableSize == 0)
- {
- throw new ArgumentException("Cache table must have atleast 1 bucket");
- }
+ ArgumentNullException.ThrowIfNull(factory);
+ ArgumentOutOfRangeException.ThrowIfZero(tableSize);
//Init bucket table
_tableSize = tableSize;
@@ -106,10 +102,7 @@ namespace VNLib.Data.Caching.ObjectCache
private uint FastGetBucketIndexFromId(ReadOnlySpan<char> objectId)
{
- if (objectId.Length < 4)
- {
- throw new ArgumentException("Object id must be larger than 3 characters");
- }
+ ArgumentOutOfRangeException.ThrowIfLessThan(objectId.Length, 4, nameof(objectId));
Span<byte> buffer = stackalloc byte[4];
diff --git a/lib/VNLib.Data.Caching.ObjectCache/src/ICacheEntryMemoryManager.cs b/lib/VNLib.Data.Caching.ObjectCache/src/ICacheEntryMemoryManager.cs
index dffbfa2..dd57931 100644
--- a/lib/VNLib.Data.Caching.ObjectCache/src/ICacheEntryMemoryManager.cs
+++ b/lib/VNLib.Data.Caching.ObjectCache/src/ICacheEntryMemoryManager.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Data.Caching.ObjectCache
@@ -57,9 +57,9 @@ namespace VNLib.Data.Caching
/// Pins the handle to the specified offset and returns a
/// <see cref="MemoryHandle"/> to the pinned memory block.
/// </summary>
- /// <param name="handle"></param>
- /// <param name="offset"></param>
- /// <returns></returns>
+ /// <param name="handle">A referrence to the existing handle</param>
+ /// <param name="offset">The number of bytes from the base to offset the returned pointer</param>
+ /// <returns>A memory handle pointing to the first byte in the segment given by the offset</returns>
MemoryHandle PinHandle(object handle, int offset);
/// <summary>
diff --git a/plugins/ObjectCacheServer/src/BucketLocalManagerFactory.cs b/plugins/ObjectCacheServer/src/BucketLocalManagerFactory.cs
index 40f4c29..e7fa3e1 100644
--- a/plugins/ObjectCacheServer/src/BucketLocalManagerFactory.cs
+++ b/plugins/ObjectCacheServer/src/BucketLocalManagerFactory.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Plugins.Extensions.VNCache
@@ -24,6 +24,7 @@
using System;
+using System.Linq;
using System.Buffers;
using System.Text.Json;
using System.Collections.Generic;
@@ -34,6 +35,8 @@ using VNLib.Utils;
using VNLib.Utils.Memory;
using VNLib.Utils.Extensions;
using VNLib.Plugins.Extensions.Loading;
+using VNLib.Utils.Memory.Diagnostics;
+using VNLib.Utils.Logging;
/*
* How bucket local memory works:
@@ -53,6 +56,8 @@ namespace VNLib.Data.Caching.ObjectCache.Server
{
private readonly LinkedList<BucketLocalManager> _managers = new ();
private readonly bool _zeroAll;
+ private readonly bool _enableHeapTracking;
+ private readonly ILogProvider _statsLogger;
///<inheritdoc/>
public ICacheEntryMemoryManager CreateForBucket(uint bucketId)
@@ -60,6 +65,13 @@ namespace VNLib.Data.Caching.ObjectCache.Server
//Init a new heap for the individual bucket
IUnmangedHeap localHeap = MemoryUtil.InitializeNewHeapForProcess();
+ if (_enableHeapTracking)
+ {
+#pragma warning disable CA2000 // Dispose objects before losing scope
+ localHeap = new TrackedHeapWrapper(localHeap, true);
+#pragma warning restore CA2000 // Dispose objects before losing scope
+ }
+
BucketLocalManager manager = new (localHeap, bucketId, _zeroAll);
_managers.AddLast(manager);
@@ -74,11 +86,31 @@ namespace VNLib.Data.Caching.ObjectCache.Server
if (config != null)
{
//Try to get the zero all flag
- if (config.TryGetValue("zero_all", out JsonElement zeroEl))
- {
- _zeroAll = zeroEl.GetBoolean();
- }
+ _zeroAll = config.TryGetValue("zero_all", out JsonElement zeroEl) && zeroEl.GetBoolean();
+
+ //Get the heap tracking flag
+ _enableHeapTracking = config.TryGetValue("diag_mem", out JsonElement trackEl) && trackEl.GetBoolean();
+ }
+
+ _statsLogger = plugin.Log.CreateScope("Cache MemStats");
+ }
+
+ public void LogHeapStats()
+ {
+ //If tracking is not enabled, the heap instances stored by the managers will not be tracked, and the cast in the code below will fail
+ if (!_enableHeapTracking)
+ {
+ return;
}
+
+ string[] statsPerHeap = _managers.Select(hm =>
+ {
+ HeapStatistics stats = (hm.Heap as TrackedHeapWrapper)!.GetCurrentStats();
+ return $"\tBucket {hm.BucketId}: Current {stats.AllocatedBytes / 1024}kB, Blocks {stats.AllocatedBlocks}, Max size {stats.MaxHeapSize / 1024}kB";
+
+ }).ToArray();
+
+ _statsLogger.Debug("Priting memory statistics for cache memory manager: {hm}\n{stats}", GetHashCode(), statsPerHeap);
}
protected override void Free()
@@ -104,7 +136,7 @@ namespace VNLib.Data.Caching.ObjectCache.Server
///<inheritdoc/>
public void FreeHandle(object handle)
{
- _ = handle ?? throw new ArgumentNullException(nameof(handle));
+ ArgumentNullException.ThrowIfNull(handle);
MemoryHandle<byte> _handle = Unsafe.As<object, MemoryHandle<byte>>(ref handle);
//Free the handle
@@ -114,7 +146,7 @@ namespace VNLib.Data.Caching.ObjectCache.Server
///<inheritdoc/>
public uint GetHandleSize(object handle)
{
- _ = handle ?? throw new ArgumentNullException(nameof(handle));
+ ArgumentNullException.ThrowIfNull(handle);
MemoryHandle<byte> _handle = Unsafe.As<object, MemoryHandle<byte>>(ref handle);
return (uint)_handle.Length;
@@ -123,7 +155,7 @@ namespace VNLib.Data.Caching.ObjectCache.Server
///<inheritdoc/>
public Span<byte> GetSpan(object handle, uint offset, uint length)
{
- _ = handle ?? throw new ArgumentNullException(nameof(handle));
+ ArgumentNullException.ThrowIfNull(handle);
MemoryHandle<byte> _handle = Unsafe.As<object, MemoryHandle<byte>>(ref handle);
return _handle.GetOffsetSpan(offset, checked((int)length));
@@ -132,7 +164,7 @@ namespace VNLib.Data.Caching.ObjectCache.Server
///<inheritdoc/>
public MemoryHandle PinHandle(object handle, int offset)
{
- _ = handle ?? throw new ArgumentNullException(nameof(handle));
+ ArgumentNullException.ThrowIfNull(handle);
MemoryHandle<byte> _handle = Unsafe.As<object, MemoryHandle<byte>>(ref handle);
//Pin the handle
@@ -142,7 +174,7 @@ namespace VNLib.Data.Caching.ObjectCache.Server
///<inheritdoc/>
public void ResizeHandle(object handle, uint newSize)
{
- _ = handle ?? throw new ArgumentNullException(nameof(handle));
+ ArgumentNullException.ThrowIfNull(handle);
MemoryHandle<byte> _handle = Unsafe.As<object, MemoryHandle<byte>>(ref handle);
//Resize the handle
diff --git a/plugins/ObjectCacheServer/src/Cache/CacheStore.cs b/plugins/ObjectCacheServer/src/Cache/CacheStore.cs
index 75abe37..86df849 100644
--- a/plugins/ObjectCacheServer/src/Cache/CacheStore.cs
+++ b/plugins/ObjectCacheServer/src/Cache/CacheStore.cs
@@ -39,19 +39,14 @@ namespace VNLib.Data.Caching.ObjectCache.Server.Cache
*/
[ConfigurationName("cache")]
- internal sealed class CacheStore : ICacheStore, IDisposable
+ internal sealed class CacheStore(PluginBase plugin, IConfigScope config) : ICacheStore, IDisposable
{
+
/// <summary>
/// Gets the underlying cache listener
/// </summary>
- public BlobCacheListener<IPeerEventQueue> Listener { get; }
-
+ public BlobCacheListener<IPeerEventQueue> Listener { get; } = InitializeCache((ObjectCacheServerEntry)plugin, config);
- public CacheStore(PluginBase plugin, IConfigScope config)
- {
- //Init cache
- Listener = InitializeCache((ObjectCacheServerEntry)plugin, config);
- }
///<inheritdoc/>
ValueTask ICacheStore.AddOrUpdateBlobAsync<T>(string objectId, string? alternateId, ObjectDataGet<T> bodyData, T state, CancellationToken token)