From 3c353afe4dffa3da9c96ef25b02f0004676afe5f Mon Sep 17 00:00:00 2001 From: vnugent Date: Sat, 14 Oct 2023 15:50:46 -0400 Subject: experimential expansion and performance changes --- .../src/BucketLocalManagerFactory.cs | 154 +++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 lib/VNLib.Plugins.Extensions.VNCache/src/BucketLocalManagerFactory.cs (limited to 'lib/VNLib.Plugins.Extensions.VNCache/src/BucketLocalManagerFactory.cs') diff --git a/lib/VNLib.Plugins.Extensions.VNCache/src/BucketLocalManagerFactory.cs b/lib/VNLib.Plugins.Extensions.VNCache/src/BucketLocalManagerFactory.cs new file mode 100644 index 0000000..cea06a3 --- /dev/null +++ b/lib/VNLib.Plugins.Extensions.VNCache/src/BucketLocalManagerFactory.cs @@ -0,0 +1,154 @@ +/* +* Copyright (c) 2023 Vaughn Nugent +* +* Library: VNLib +* Package: ObjectCacheServer +* File: BucketLocalManagerFactory.cs +* +* BucketLocalManagerFactory.cs is part of ObjectCacheServer which is part of the larger +* VNLib collection of libraries and utilities. +* +* ObjectCacheServer 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. +* +* ObjectCacheServer 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; + +namespace VNLib.Data.Caching.ObjectCache.Server +{ + [ConfigurationName("memory_manager", Required = false)] + internal sealed class BucketLocalManagerFactory : VnDisposeable, ICacheMemoryManagerFactory + { + private readonly LinkedList _managers = new (); + private readonly bool _zeroAll; + + /// + public ICacheEntryMemoryManager CreateForBucket(uint bucketId) + { + //Init a new heap for a individual bucket + IUnmangedHeap localHeap = MemoryUtil.InitializeNewHeapForProcess(); + + BucketLocalManager manager = new (localHeap, bucketId, _zeroAll); + _managers.AddLast(manager); + + return manager; + } + + /// + /// Creates a new with the specified zero all flag + /// that is not managed by a plugin instance + /// + /// Forces all allocations to be zeroed before being returned to callers + /// + public static BucketLocalManagerFactory Create(bool zeroAll) => new (zeroAll); + + private BucketLocalManagerFactory(bool zeroAll) + { + _zeroAll = zeroAll; + } + + 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 + { + + /// + public object AllocHandle(uint size) => Heap.Alloc(size, Zero); + + /// + public void FreeHandle(object handle) + { + _ = handle ?? throw new ArgumentNullException(nameof(handle)); + MemoryHandle _handle = Unsafe.As>(ref handle); + + //Free the handle + _handle.Dispose(); + } + + /// + public uint GetHandleSize(object handle) + { + _ = handle ?? throw new ArgumentNullException(nameof(handle)); + MemoryHandle _handle = Unsafe.As>(ref handle); + + return (uint)_handle.Length; + } + + /// + public Span GetSpan(object handle, uint offset, uint length) + { + _ = handle ?? throw new ArgumentNullException(nameof(handle)); + MemoryHandle _handle = Unsafe.As>(ref handle); + + return _handle.GetOffsetSpan(offset, checked((int)length)); + } + + /// + public MemoryHandle PinHandle(object handle, int offset) + { + _ = handle ?? throw new ArgumentNullException(nameof(handle)); + MemoryHandle _handle = Unsafe.As>(ref handle); + + //Pin the handle + return _handle.Pin(offset); + } + + /// + public void ResizeHandle(object handle, uint newSize) + { + _ = handle ?? throw new ArgumentNullException(nameof(handle)); + MemoryHandle _handle = Unsafe.As>(ref handle); + + //Resize the handle + _handle.ResizeIfSmaller(newSize); + } + } + } +} -- cgit