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 }
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 }
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. }
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 }
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; } }
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 }
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 }
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. }