public void PoolPerformance() { const int perCoreCapacity = 20; int capacity = Environment.ProcessorCount * perCoreCapacity; Func <DummyPoolable> dummyFactory = () => new DummyPoolable(); var mpmcPool = new MPMCPoolCore <DummyPoolable>(dummyFactory, capacity); var objectPool = new ObjectPoolCore <DummyPoolable>(dummyFactory, capacity); var lockedObjectPool = new LockedObjectPoolCore <DummyPoolable>(dummyFactory, capacity); var perCoreMPMCPool = new MPMCPool <DummyPoolable>(dummyFactory, perCoreCapacity); var perCoreObjectPool = new ObjectPool <DummyPoolable>(dummyFactory, perCoreCapacity); var perCoreLockedObjectPool = new LockedObjectPool <DummyPoolable>(dummyFactory, perCoreCapacity); var threads = new int[] { 1, 2, 4, 6, 8, 12, 24 }; foreach (var t in threads) { for (int round = 0; round < 20; round++) { // MPMCBenchmark(); // PoolBenchmark(mpmcPool, "MPMC", t); // PoolBenchmark(objectPool, "OP", t); // PoolBenchmark(lockedObjectPool, "LOP", t); // PoolBenchmark(perCoreMPMCPool, "pcMPMC", t); // PoolBenchmark(perCoreObjectPool, "pcOP", t); PoolBenchmark(perCoreLockedObjectPool, "pcLOP", t); } } Benchmark.Dump(); }
public ArrayMemorySliceBucket(int bufferLength, int maxBufferCount) { if (!BitUtil.IsPowerOfTwo(bufferLength) || bufferLength >= Settings.SlabLength) { ThrowHelper.ThrowArgumentException("bufferLength must be a power of two max 64MB"); } _bufferLength = bufferLength; // NOTE: allocateOnEmpty = true _pool = new LockedObjectPool <ArrayMemorySlice <T> >(maxBufferCount, Factory, allocateOnEmpty: true); _slab = ArrayMemory <T> .Create(Settings.SlabLength, true); _slabFreeCount = _slab.Length / _bufferLength; }
public unsafe ArrayMemorySlice(ArrayMemory <T> slab, LockedObjectPool <ArrayMemorySlice <T> > slicesPool, int offset, int length) { if (!TypeHelper <T> .IsPinnable) { ThrowHelper.FailFast("Do not use slices for not pinnable"); } #pragma warning disable 618 _slab = slab; _slab.Increment(); _pointer = Unsafe.Add <T>(_slab.Pointer, offset); _handle = GCHandle.Alloc(_slab); #pragma warning restore 618 _slicesPool = slicesPool; _length = length; _array = slab._array; _arrayOffset = slab._arrayOffset + offset; }
/// <summary> /// Open the environment. /// </summary> public void Open() { CreateDirectoryIfMissing(); if (!_isOpen) { var ptr = NativeMethods.StringToHGlobalUTF8(_directory); NativeMethods.AssertExecute(NativeMethods.mdb_env_open(_handle, ptr, _openFlags, _accessMode)); if (ptr != IntPtr.Zero) { Marshal.FreeHGlobal(ptr); } } _isOpen = true; var maxPooledReaders = Math.Max(16, Math.Min(Environment.ProcessorCount * 2, MaxReaders - Environment.ProcessorCount * 2)); var poolSize = _disableReadTxnAutoreset ? 1 : maxPooledReaders; ReadTxnPool = new LockedObjectPool <TransactionImpl>(poolSize, () => { return(null); }, false); }
public void PoolUnbalancedRentReturn() { const int perCoreCapacity = 50; Func <DummyPoolable> dummyFactory = () => new DummyPoolable(); var perCoreLockedObjectPool = new LockedObjectPool <DummyPoolable>(dummyFactory, perCoreCapacity, allocateOnEmpty: false); var queues = Enumerable.Range(0, 4) .Select(x => new SingleProducerSingleConsumerQueue <DummyPoolable>()).ToArray(); var cts = new CancellationTokenSource(); var totalCount = 0L; Task[] producers = new Task[queues.Length]; Task[] consumers = new Task[queues.Length]; var sw = Stopwatch.StartNew(); for (int i = 0; i < queues.Length; i++) { var queue = queues[i]; producers[i] = Task.Factory.StartNew(() => { var count = 0L; while (!cts.IsCancellationRequested) { var item = perCoreLockedObjectPool.Rent(); if (item != null) { queue.Enqueue(item); count++; } } Interlocked.Add(ref totalCount, count); }); consumers[i] = Task.Factory.StartNew(() => { var count = 0L; while (!cts.IsCancellationRequested) { if (queue.TryDequeue(out var item)) { perCoreLockedObjectPool.Return(item); count++; } } Interlocked.Add(ref totalCount, count); }); } Thread.Sleep(5_000); cts.Cancel(); Task.WaitAll(producers); Task.WaitAll(consumers); sw.Stop(); Console.WriteLine( $"MOPS: {(totalCount / 1000000.0) / (sw.ElapsedMilliseconds / 1000.0):N2}, Total count: {totalCount:N0}, elapsed: {sw.ElapsedMilliseconds:N0}"); }
internal Database(string name, TransactionImpl txn, DatabaseConfig config) { if (txn.IsReadOnly) { throw new InvalidOperationException("Cannot create a DB with RO transaction"); } if (txn == null) { throw new ArgumentNullException(nameof(txn)); } _config = config ?? throw new ArgumentNullException(nameof(config)); _name = name; _environment = txn.LmdbEnvironment; _environmentGcHandle = GCHandle.Alloc(_environment, GCHandleType.Normal); NativeMethods.AssertExecute(NativeMethods.mdb_dbi_open(txn.Handle, name, _config.OpenFlags, out var handle)); if (_config.CompareFunction != null) { NativeMethods.AssertExecute(NativeMethods.mdb_set_compare(txn.Handle, handle, _config.CompareFunction)); } if (_config.DupSortFunction != null) { NativeMethods.AssertExecute(NativeMethods.mdb_set_dupsort(txn.Handle, handle, _config.DupSortFunction)); } if (_config.DupSortPrefix > 0) { if (_config.DupSortPrefix == 64 * 64) { NativeMethods.AssertExecute(NativeMethods.sdb_set_dupsort_as_uint64x64(txn.Handle, handle)); } else if (_config.DupSortPrefix == 128) { NativeMethods.AssertExecute(NativeMethods.sdb_set_dupsort_as_uint128(txn.Handle, handle)); } else if (_config.DupSortPrefix == 96) { NativeMethods.AssertExecute(NativeMethods.sdb_set_dupsort_as_uint96(txn.Handle, handle)); } else if (_config.DupSortPrefix == 80) { NativeMethods.AssertExecute(NativeMethods.sdb_set_dupsort_as_uint80(txn.Handle, handle)); } else if (_config.DupSortPrefix == 64) { NativeMethods.AssertExecute(NativeMethods.sdb_set_dupsort_as_uint64(txn.Handle, handle)); } else if (_config.DupSortPrefix == 48) { NativeMethods.AssertExecute(NativeMethods.sdb_set_dupsort_as_uint48(txn.Handle, handle)); } else if (_config.DupSortPrefix == 32) { NativeMethods.AssertExecute(NativeMethods.sdb_set_dupsort_as_uint32(txn.Handle, handle)); } else if (_config.DupSortPrefix == 16) { NativeMethods.AssertExecute(NativeMethods.sdb_set_dupsort_as_uint16(txn.Handle, handle)); } else { throw new NotSupportedException("Rethink your design if you need this!"); } } _handle = handle; var poolSize = System.Environment.ProcessorCount * 2; ReadCursorPool = new LockedObjectPool <CursorImpl>(() => null, poolSize, false); }