public AllocatedMemoryData Allocate(int size)
        {
            if (_isDisposed)
            {
                ThrowAlreadyDisposedException();
            }
#if MEM_GUARD
            return(new AllocatedMemoryData
            {
                Address = ElectricFencedMemory.Allocate(size),
                SizeInBytes = size
            });
#else
            if (_used + size > _allocated)
            {
                GrowArena(size);
            }

            var allocation = new AllocatedMemoryData()
            {
                SizeInBytes = size,
                Address     = _ptrCurrent
            };

            _ptrCurrent += size;
            _used       += size;

            return(allocation);
#endif
        }
示例#2
0
        public AllocatedMemoryData Allocate(int size)
        {
#if MEM_GUARD
            return(new AllocatedMemoryData
            {
                SizeInBytes = size,
                Address = ElectricFencedMemory.Allocate(size),
            });
#else
            var actualSize = Bits.PowerOf2(size);

            var index = GetIndexFromSize(actualSize);

            NativeMemory.ThreadStats stats;
            if (index == -1)
            {
                return(new AllocatedMemoryData(NativeMemory.AllocateMemory(size, out stats), size)
                {
                    AllocatingThread = stats
                });
            }

            actualSize = GetIndexSize(ref index, actualSize); // when we request 7 bytes, we want to get 16 bytes

            if (_freeSegments[index].TryPop(out AllocatedMemoryData list))
            {
                return(list);
            }
            return(new AllocatedMemoryData(NativeMemory.AllocateMemory(actualSize, out stats), actualSize)
            {
                AllocatingThread = stats
            });
#endif
        }
示例#3
0
        public AllocatedMemoryData Allocate(int size)
        {
            if (_isDisposed)
            {
                goto ErrorDisposed;
            }

            if (_ptrStart == null)
            {
                goto ErrorResetted;
            }

#if MEM_GUARD
            return(new AllocatedMemoryData
            {
                Address = ElectricFencedMemory.Allocate(size),
                SizeInBytes = size
            });
#else
            size = Bits.NextPowerOf2(Math.Max(sizeof(FreeSection), size));

            AllocatedMemoryData allocation;

            var index = Bits.MostSignificantBit(size) - 1;
            if (_freed[index] != null)
            {
                var section = _freed[index];
                _freed[index] = section->Previous;

                allocation = new AllocatedMemoryData
                {
                    Address     = (byte *)section,
                    SizeInBytes = section->SizeInBytes
                };
                goto Return;
            }

            if (_used + size > _allocated)
            {
                GrowArena(size);
            }

            allocation = new AllocatedMemoryData
            {
                SizeInBytes = size,
                Address     = _ptrCurrent
            };

            _ptrCurrent += size;
            _used       += size;
            TotalUsed   += size;

            Return : return(allocation);
#endif

            ErrorDisposed : ThrowAlreadyDisposedException();
            ErrorResetted : ThrowInvalidAllocateFromResetWithoutRenew();
            return(null); // Will never happen.
        }
示例#4
0
        public void Return(AllocatedMemoryData allocation)
        {
            if (_isDisposed ?? true)
            {
                return;
            }


            var address = allocation.Address;

#if DEBUG
            Debug.Assert(address != _ptrCurrent);
            Debug.Assert(allocation.IsReturned == false);
            allocation.IsReturned = true;
#endif

#if MEM_GUARD
#if MEM_GUARD_STACK
            if (allocation.FreedBy == null)
            {
                allocation.FreedBy = Environment.StackTrace;
            }
#endif
            ElectricFencedMemory.Free(address);
#else
            if (address != _ptrCurrent - allocation.SizeInBytes ||
                address < _ptrStart)
            {
                // we have fragmentation, so'll just store the values that we need here
                // in the memory we just freed :-)

                // note that this fragmentation will be healed by the call to ResetArena
                // trying to do this on the fly is too expensive.

                Debug.Assert(Bits.PowerOf2(allocation.SizeInBytes) == allocation.SizeInBytes,
                             "Allocation size must always be a power of two"
                             );
                Debug.Assert(allocation.SizeInBytes >= sizeof(FreeSection));


                var index   = Bits.MostSignificantBit(allocation.SizeInBytes) - 1;
                var section = (FreeSection *)address;
                section->SizeInBytes = allocation.SizeInBytes;
                section->Previous    = _freed[index];
                _freed[index]        = section;
                return;
            }
            // since the returned allocation is at the end of the arena, we can just move
            // the pointer back
            _used       -= allocation.SizeInBytes;
            TotalUsed   -= allocation.SizeInBytes;
            _ptrCurrent -= allocation.SizeInBytes;
#endif
        }
        public JsonOperationContext(int initialSize, int longLivedSize, SharedMultipleUseFlag lowMemoryFlag)
        {
            Debug.Assert(lowMemoryFlag != null);
            _disposeOnceRunner = new DisposeOnce <ExceptionRetry>(() =>
            {
#if MEM_GUARD_STACK
                ElectricFencedMemory.DecrementConext();
                ElectricFencedMemory.UnRegisterContextAllocation(this);
#endif

                Reset(true);

                _documentBuilder.Dispose();
                _arenaAllocator.Dispose();
                _arenaAllocatorForLongLivedValues?.Dispose();

                if (_managedBuffers != null)
                {
                    foreach (var managedPinnedBuffer in _managedBuffers)
                    {
                        managedPinnedBuffer.Dispose();
                    }

                    _managedBuffers = null;
                }

                if (_pinnedObjects != null)
                {
                    foreach (var pinnedObject in _pinnedObjects)
                    {
                        pinnedObject.Free();
                    }

                    _pinnedObjects = null;
                }
            });

            _initialSize    = initialSize;
            _longLivedSize  = longLivedSize;
            _arenaAllocator = new ArenaMemoryAllocator(lowMemoryFlag, initialSize);
            _arenaAllocatorForLongLivedValues = new ArenaMemoryAllocator(lowMemoryFlag, longLivedSize);
            CachedProperties  = new CachedProperties(this);
            _jsonParserState  = new JsonParserState();
            _objectJsonParser = new ObjectJsonParser(_jsonParserState, this);
            _documentBuilder  = new BlittableJsonDocumentBuilder(this, _jsonParserState, _objectJsonParser);
            LowMemoryFlag     = lowMemoryFlag;

#if MEM_GUARD_STACK
            ElectricFencedMemory.IncrementConext();
            ElectricFencedMemory.RegisterContextAllocation(this, Environment.StackTrace);
#endif
        }
        public void Return(AllocatedMemoryData allocation)
        {
#if MEM_GUARD
#if MEM_GUARD_STACK
            allocation.FreedBy = Environment.StackTrace;
#endif
            ElectricFencedMemory.Free(allocation.Address);
#else
            if (allocation.Address != _ptrCurrent - allocation.SizeInBytes ||
                allocation.Address < _ptrStart)
            {
                if (_fragements == null)
                {
                    _fragements = new SortedList <long, AllocatedMemoryData>();
                }
                // we have fragmentation, let us try to heal it
                _fragements.Add((long)allocation.Address, allocation);
                return;
            }
            // since the returned allocation is at the end of the arena, we can just move
            // the pointer back
            _used       -= allocation.SizeInBytes;
            _ptrCurrent -= allocation.SizeInBytes;

            if (_fragements == null)
            {
                return;
            }

            // let us try to heal fragmentation at this point
            while (_fragements.Count > 0)
            {
                var highest = _fragements.Values[_fragements.Count - 1];
                if (highest.Address != _ptrCurrent - allocation.SizeInBytes)
                {
                    break;
                }
                _fragements.RemoveAt(_fragements.Count - 1);
                if (highest.Address < _ptrStart)
                {
                    // this is from another segment, probably, currently we'll just ignore it,
                    // we might want to track if all the memory from a previous segment has been
                    // released, and then free it, but not for now
                    continue;
                }
                _used       -= highest.SizeInBytes;
                _ptrCurrent -= highest.SizeInBytes;
            }
#endif
        }
示例#7
0
        public override void Dispose()
        {
            if (_disposed)
            {
                return;
            }

            lock (this)
            {
                if (_disposed)
                {
                    return;
                }


#if MEM_GUARD_STACK
                ElectricFencedMemory.DecrementConext();
                ElectricFencedMemory.UnRegisterContextAllocation(this);
#endif

                Reset(true);

                _documentBuilder.Dispose();

                _arenaAllocator.Dispose();
                _arenaAllocatorForLongLivedValues?.Dispose();

                if (_managedBuffers != null)
                {
                    foreach (var managedPinnedBuffer in _managedBuffers)
                    {
                        managedPinnedBuffer.Dispose();
                    }
                    _managedBuffers = null;
                }

                if (_pinnedObjects != null)
                {
                    foreach (var pinnedObject in _pinnedObjects)
                    {
                        pinnedObject.Free();
                    }
                }

                _disposed = true;
            }
        }
示例#8
0
        public void Return(AllocatedMemoryData returned)
        {
#if MEM_GUARD
            ElectricFencedMemory.Free(returned.Address);
#else
            if (returned == null)
            {
                throw new ArgumentNullException(nameof(returned));
            }
            var index = GetIndexFromSize(returned.SizeInBytes);
            if (index == -1)
            {
                NativeMemory.Free(returned.Address, returned.SizeInBytes, returned.AllocatingThread);

                return; // strange size, just free it
            }
            _freeSegments[index].Push(returned);
#endif
        }
示例#9
0
        public JsonOperationContext(int initialSize, int longLivedSize, SharedMultipleUseFlag lowMemoryFlag)
        {
            Debug.Assert(lowMemoryFlag != null);

            _initialSize    = initialSize;
            _longLivedSize  = longLivedSize;
            _arenaAllocator = new ArenaMemoryAllocator(lowMemoryFlag, initialSize);
            _arenaAllocatorForLongLivedValues = new ArenaMemoryAllocator(lowMemoryFlag, longLivedSize);
            CachedProperties  = new CachedProperties(this);
            _jsonParserState  = new JsonParserState();
            _objectJsonParser = new ObjectJsonParser(_jsonParserState, this);
            _documentBuilder  = new BlittableJsonDocumentBuilder(this, _jsonParserState, _objectJsonParser);
            LowMemoryFlag     = lowMemoryFlag;

#if MEM_GUARD_STACK
            ElectricFencedMemory.IncrementConext();
            ElectricFencedMemory.RegisterContextAllocation(this, Environment.StackTrace);
#endif
        }
示例#10
0
        public AllocatedMemoryData Allocate(int size)
        {
            if (_isDisposed ?? true)
            {
                goto ErrorDisposed;
            }

            if (_ptrStart == null)
            {
                goto ErrorResetted;
            }

#if MEM_GUARD
            return(new AllocatedMemoryData
            {
                Address = ElectricFencedMemory.Allocate(size),
                SizeInBytes = size
            });
#else
            if (size < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(size), size,
                                                      $"Size cannot be negative");
            }

            if (size > MaxArenaSize)
            {
                throw new ArgumentOutOfRangeException(nameof(size), size,
                                                      $"Requested size {size} while maximum size is {MaxArenaSize}");
            }

            size = Bits.PowerOf2(Math.Max(sizeof(FreeSection), size));

            AllocatedMemoryData allocation;

            var index = Bits.MostSignificantBit(size) - 1;
            if (_freed[index] != null)
            {
                var section = _freed[index];
                _freed[index] = section->Previous;

                allocation = new AllocatedMemoryData((byte *)section, section->SizeInBytes);
                goto Return;
            }

            if (_used + size > _allocated)
            {
                GrowArena(size);
            }

            allocation = new AllocatedMemoryData(_ptrCurrent, size);

            _ptrCurrent += size;
            _used       += size;
            TotalUsed   += size;

Return:
            return(allocation);
#endif

ErrorDisposed:
            ThrowAlreadyDisposedException();
ErrorResetted:
            ThrowInvalidAllocateFromResetWithoutRenew();
            return(null); // Will never happen.
        }