diff options
Diffstat (limited to 'plugins/ObjectCacheServer/src')
6 files changed, 168 insertions, 15 deletions
diff --git a/plugins/ObjectCacheServer/src/BucketLocalManagerFactory.cs b/plugins/ObjectCacheServer/src/BucketLocalManagerFactory.cs new file mode 100644 index 0000000..40f4c29 --- /dev/null +++ b/plugins/ObjectCacheServer/src/BucketLocalManagerFactory.cs @@ -0,0 +1,153 @@ +/* +* Copyright (c) 2023 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Plugins.Extensions.VNCache +* File: BucketLocalManagerFactory.cs +* +* BucketLocalManagerFactory.cs is part of VNLib.Plugins.Extensions.VNCache +* which is part of the larger VNLib collection of libraries and utilities. +* +* VNLib.Plugins.Extensions.VNCache is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* VNLib.Plugins.Extensions.VNCache is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ + + +using System; +using System.Buffers; +using System.Text.Json; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +using VNLib.Plugins; +using VNLib.Utils; +using VNLib.Utils.Memory; +using VNLib.Utils.Extensions; +using VNLib.Plugins.Extensions.Loading; + +/* + * How bucket local memory works: + * + * The object cache library allows us to create a memory manager for use with + * an individual bucket. Each bucket is mutually exclusive, so memory operations + * are "thread-safe" This means we can create a heap for each bucket and use it + * for all memory operations for that bucket. Since no contention will occur, + * we can get a little more performance out of the memory operations. The internal + * heap impls will still likely have locks enabled, but no contention will occur + */ + +namespace VNLib.Data.Caching.ObjectCache.Server +{ + [ConfigurationName("memory_manager", Required = false)] + internal sealed class BucketLocalManagerFactory : VnDisposeable, ICacheMemoryManagerFactory + { + private readonly LinkedList<BucketLocalManager> _managers = new (); + private readonly bool _zeroAll; + + ///<inheritdoc/> + public ICacheEntryMemoryManager CreateForBucket(uint bucketId) + { + //Init a new heap for the individual bucket + IUnmangedHeap localHeap = MemoryUtil.InitializeNewHeapForProcess(); + + BucketLocalManager manager = new (localHeap, bucketId, _zeroAll); + _managers.AddLast(manager); + + return manager; + } + + public BucketLocalManagerFactory(PluginBase plugin) : this(plugin, null) + { } + + public BucketLocalManagerFactory(PluginBase plugin, IConfigScope? config) + { + if (config != null) + { + //Try to get the zero all flag + if (config.TryGetValue("zero_all", out JsonElement zeroEl)) + { + _zeroAll = zeroEl.GetBoolean(); + } + } + } + + protected override void Free() + { + //Free heaps on exit + foreach (BucketLocalManager manager in _managers) + { + manager.Heap.Dispose(); + } + } + + /* + * Buckets are mutually exclusive, so we can use a single heap for each bucket + * to get a little more performance on memory operations + */ + + private sealed record class BucketLocalManager(IUnmangedHeap Heap, uint BucketId, bool Zero) : ICacheEntryMemoryManager + { + + ///<inheritdoc/> + public object AllocHandle(uint size) => Heap.Alloc<byte>(size, Zero); + + ///<inheritdoc/> + public void FreeHandle(object handle) + { + _ = handle ?? throw new ArgumentNullException(nameof(handle)); + MemoryHandle<byte> _handle = Unsafe.As<object, MemoryHandle<byte>>(ref handle); + + //Free the handle + _handle.Dispose(); + } + + ///<inheritdoc/> + public uint GetHandleSize(object handle) + { + _ = handle ?? throw new ArgumentNullException(nameof(handle)); + MemoryHandle<byte> _handle = Unsafe.As<object, MemoryHandle<byte>>(ref handle); + + return (uint)_handle.Length; + } + + ///<inheritdoc/> + public Span<byte> GetSpan(object handle, uint offset, uint length) + { + _ = handle ?? throw new ArgumentNullException(nameof(handle)); + MemoryHandle<byte> _handle = Unsafe.As<object, MemoryHandle<byte>>(ref handle); + + return _handle.GetOffsetSpan(offset, checked((int)length)); + } + + ///<inheritdoc/> + public MemoryHandle PinHandle(object handle, int offset) + { + _ = handle ?? throw new ArgumentNullException(nameof(handle)); + MemoryHandle<byte> _handle = Unsafe.As<object, MemoryHandle<byte>>(ref handle); + + //Pin the handle + return _handle.Pin(offset); + } + + ///<inheritdoc/> + public void ResizeHandle(object handle, uint newSize) + { + _ = handle ?? throw new ArgumentNullException(nameof(handle)); + MemoryHandle<byte> _handle = Unsafe.As<object, MemoryHandle<byte>>(ref handle); + + //Resize the handle + _handle.ResizeIfSmaller(newSize); + } + } + } +} diff --git a/plugins/ObjectCacheServer/src/Cache/CacheStore.cs b/plugins/ObjectCacheServer/src/Cache/CacheStore.cs index f94a3f5..5795222 100644 --- a/plugins/ObjectCacheServer/src/Cache/CacheStore.cs +++ b/plugins/ObjectCacheServer/src/Cache/CacheStore.cs @@ -107,11 +107,14 @@ Cache Configuration: //Get the event listener ICacheListenerEventQueue queue = plugin.GetOrCreateSingleton<CacheListenerPubQueue>(); + //Get the memory manager + ICacheMemoryManagerFactory manager = plugin.GetOrCreateSingleton<BucketLocalManagerFactory>(); + //Load the blob cache table system - IBlobCacheTable bc = plugin.LoadMemoryCacheSystem(config, plugin.CacheHeap, cacheConf); + IBlobCacheTable bc = plugin.LoadMemoryCacheSystem(config, manager, cacheConf); //Endpoint only allows for a single reader - return new(bc, queue, plugin.Log, plugin.CacheHeap); + return new(bc, queue, plugin.Log, plugin.ListenerHeap); } /* diff --git a/plugins/ObjectCacheServer/src/Cache/CacheSystemUtil.cs b/plugins/ObjectCacheServer/src/Cache/CacheSystemUtil.cs index 2071d2b..a02fe75 100644 --- a/plugins/ObjectCacheServer/src/Cache/CacheSystemUtil.cs +++ b/plugins/ObjectCacheServer/src/Cache/CacheSystemUtil.cs @@ -30,7 +30,6 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; using VNLib.Plugins; -using VNLib.Utils.Memory; using VNLib.Plugins.Extensions.Loading; namespace VNLib.Data.Caching.ObjectCache.Server.Cache @@ -52,7 +51,7 @@ namespace VNLib.Data.Caching.ObjectCache.Server.Cache /// <param name="cacheConf">The cache configuration object</param> /// <returns>The loaded <see cref="IBlobCacheTable"/> implementation</returns> /// <exception cref="FileNotFoundException"></exception> - public static IBlobCacheTable LoadMemoryCacheSystem(this PluginBase plugin, IConfigScope config, IUnmangedHeap heap, CacheConfiguration cacheConf) + public static IBlobCacheTable LoadMemoryCacheSystem(this PluginBase plugin, IConfigScope config, ICacheMemoryManagerFactory heap, CacheConfiguration cacheConf) { //First, try to load persitant cache store PersistantCacheManager? pCManager = GetPersistantStore(plugin, config); @@ -79,7 +78,7 @@ namespace VNLib.Data.Caching.ObjectCache.Server.Cache return table; } - private static IBlobCacheTable GetInternalBlobCache(IUnmangedHeap heap, CacheConfiguration config, IPersistantCacheStore? store) + private static IBlobCacheTable GetInternalBlobCache(ICacheMemoryManagerFactory heap, CacheConfiguration config, IPersistantCacheStore? store) { return new BlobCacheTable(config.BucketCount, config.MaxCacheEntries, heap, store); } diff --git a/plugins/ObjectCacheServer/src/Clustering/CacheNodeReplicationMaanger.cs b/plugins/ObjectCacheServer/src/Clustering/CacheNodeReplicationMaanger.cs index 5a04737..19f09dc 100644 --- a/plugins/ObjectCacheServer/src/Clustering/CacheNodeReplicationMaanger.cs +++ b/plugins/ObjectCacheServer/src/Clustering/CacheNodeReplicationMaanger.cs @@ -76,11 +76,11 @@ namespace VNLib.Data.Caching.ObjectCache.Server.Clustering //Load the node config _nodeConfig = plugin.GetOrCreateSingleton<NodeConfig>(); _cacheStore = plugin.GetOrCreateSingleton<CacheStore>(); - _peerAdapter = plugin.GetOrCreateSingleton<PeerDiscoveryManager>(); + _peerAdapter = plugin.GetOrCreateSingleton<PeerDiscoveryManager>(); //Init fbm config with fixed message size _replicationClientConfig = FBMDataCacheExtensions.GetDefaultConfig( - (plugin as ObjectCacheServerEntry)!.CacheHeap, + (plugin as ObjectCacheServerEntry)!.ListenerHeap, MAX_MESSAGE_SIZE, debugLog: plugin.IsDebug() ? plugin.Log : null ); diff --git a/plugins/ObjectCacheServer/src/Clustering/PeerDiscoveryManager.cs b/plugins/ObjectCacheServer/src/Clustering/PeerDiscoveryManager.cs index 65cc009..6475f9c 100644 --- a/plugins/ObjectCacheServer/src/Clustering/PeerDiscoveryManager.cs +++ b/plugins/ObjectCacheServer/src/Clustering/PeerDiscoveryManager.cs @@ -135,7 +135,7 @@ namespace VNLib.Data.Caching.ObjectCache.Server.Clustering if (allAds.Length > 0) { - //Discover all kown nodes + //Discover all known nodes await Config.Config.DiscoverNodesAsync(allAds, exitToken); } diff --git a/plugins/ObjectCacheServer/src/ObjectCacheServerEntry.cs b/plugins/ObjectCacheServer/src/ObjectCacheServerEntry.cs index a566390..aada787 100644 --- a/plugins/ObjectCacheServer/src/ObjectCacheServerEntry.cs +++ b/plugins/ObjectCacheServer/src/ObjectCacheServerEntry.cs @@ -32,6 +32,7 @@ using VNLib.Utils.Logging; using VNLib.Utils.Memory.Diagnostics; using VNLib.Plugins.Extensions.Loading; using VNLib.Plugins.Extensions.Loading.Routing; + using VNLib.Data.Caching.ObjectCache.Server.Endpoints; using VNLib.Data.Caching.ObjectCache.Server.Clustering; @@ -42,12 +43,9 @@ namespace VNLib.Data.Caching.ObjectCache.Server { public override string PluginName => "ObjectCache.Service"; - private readonly Lazy<IUnmangedHeap> _cacheHeap; + private readonly Lazy<IUnmangedHeap> _cacheHeap; - /// <summary> - /// Gets the shared heap for the plugin - /// </summary> - internal IUnmangedHeap CacheHeap => _cacheHeap.Value; + internal IUnmangedHeap ListenerHeap => _cacheHeap.Value; public ObjectCacheServerEntry() { @@ -55,14 +53,14 @@ namespace VNLib.Data.Caching.ObjectCache.Server _cacheHeap = new Lazy<IUnmangedHeap>(InitializeHeap, LazyThreadSafetyMode.PublicationOnly); } - private IUnmangedHeap InitializeHeap() + internal IUnmangedHeap InitializeHeap() { //Create default heap IUnmangedHeap _heap = MemoryUtil.InitializeNewHeapForProcess(); try { //If the plugin is in debug mode enable heap tracking - return this.IsDebug() ? new TrackedHeapWrapper(_heap) : _heap; + return this.IsDebug() ? new TrackedHeapWrapper(_heap, true) : _heap; } catch { |