/// <summary> /// Internal function called by the plugin to remove old, non-used buffers. /// </summary> internal static void Maintain() { DateTime now = DateTime.UtcNow; if (!_isEnabled || lastMaintenance + RunMaintenanceEvery > now) { return; } lastMaintenance = now; DateTime olderThan = now - RemoveOlderThan; rwLock.EnterWriteLock(); try { //if (HTTPManager.Logger.Level == Logger.Loglevels.All) // HTTPManager.Logger.Information("VariableSizedBufferPool", "Before Maintain: " + GetStatistics()); for (int i = 0; i < FreeBuffers.Count; ++i) { BufferStore store = FreeBuffers[i]; List <BufferDesc> buffers = store.buffers; for (int cv = buffers.Count - 1; cv >= 0; cv--) { BufferDesc desc = buffers[cv]; if (desc.released < olderThan) { // buffers stores available buffers ascending by age. So, when we find an old enough, we can // delete all entries in the [0..cv] range. int removeCount = cv + 1; buffers.RemoveRange(0, removeCount); PoolSize -= (int)(removeCount * store.Size); break; } } if (RemoveEmptyLists && buffers.Count == 0) { FreeBuffers.RemoveAt(i--); } } //if (HTTPManager.Logger.Level == Logger.Loglevels.All) // HTTPManager.Logger.Information("VariableSizedBufferPool", "After Maintain: " + GetStatistics()); } finally { rwLock.ExitWriteLock(); } }
/// <summary> /// Get byte[] from the pool. If canBeLarge is true, the returned buffer might be larger than the requested size. /// </summary> public static byte[] Get(long size, bool canBeLarger) { if (!_isEnabled) { return(new byte[size]); } // Return a fix reference for 0 length requests. Any resize call (even Array.Resize) creates a new reference // so we are safe to expose it to multiple callers. if (size == 0) { return(VariableSizedBufferPool.NoData); } lock (FreeBuffers) { if (FreeBuffers.Count == 0) { return(new byte[size]); } BufferDesc bufferDesc = FindFreeBuffer(size, canBeLarger); if (bufferDesc.buffer == null) { if (canBeLarger) { if (size < MinBufferSize) { size = MinBufferSize; } else if (!IsPowerOfTwo(size)) { size = NextPowerOf2(size); } } return(new byte[size]); } else { GetBuffers++; } PoolSize -= bufferDesc.buffer.Length; return(bufferDesc.buffer); } }
private static BufferDesc FindFreeBuffer(long size, bool canBeLarger) { for (int i = 0; i < FreeBuffers.Count; ++i) { BufferStore store = FreeBuffers[i]; if (store.buffers.Count > 0 && (store.Size == size || (canBeLarger && store.Size > size))) { // Getting the last one has two desired effect: // 1.) RemoveAt should be quicker as it don't have to move all the remaining entries // 2.) Old, non-used buffers will age. Getting a buffer and putting it back will not keep buffers fresh. BufferDesc lastFree = store.buffers[store.buffers.Count - 1]; store.buffers.RemoveAt(store.buffers.Count - 1); return(lastFree); } } return(BufferDesc.Empty); }