Exemple #1
0
        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();
        }
Exemple #2
0
        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;
        }
Exemple #3
0
        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);
        }
Exemple #5
0
        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}");
        }
Exemple #6
0
        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);
        }