Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / System.Runtime.DurableInstancing / System / Runtime / InternalBufferManager.cs / 1305376 / InternalBufferManager.cs
//---------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //--------------------------------------------------------------------------- namespace System.Runtime { using System; using System.Collections.Generic; using System.Threading; abstract class InternalBufferManager { protected InternalBufferManager() { } public abstract byte[] TakeBuffer(int bufferSize); public abstract void ReturnBuffer(byte[] buffer); public abstract void Clear(); public static InternalBufferManager Create(long maxBufferPoolSize, int maxBufferSize) { if (maxBufferPoolSize == 0) { return GCBufferManager.Value; } else { Fx.Assert(maxBufferPoolSize > 0 && maxBufferSize >= 0, "bad params, caller should verify"); return new PooledBufferManager(maxBufferPoolSize, maxBufferSize); } } class PooledBufferManager : InternalBufferManager { const int minBufferSize = 128; const int maxMissesBeforeTuning = 8; const int initialBufferCount = 1; readonly object tuningLock; int[] bufferSizes; BufferPool[] bufferPools; long memoryLimit; long remainingMemory; bool areQuotasBeingTuned; int totalMisses; public PooledBufferManager(long maxMemoryToPool, int maxBufferSize) { this.tuningLock = new object(); this.memoryLimit = maxMemoryToPool; this.remainingMemory = maxMemoryToPool; ListbufferPoolList = new List (); for (int bufferSize = minBufferSize; ; ) { long bufferCountLong = this.remainingMemory / bufferSize; int bufferCount = bufferCountLong > int.MaxValue ? int.MaxValue : (int)bufferCountLong; if (bufferCount > initialBufferCount) { bufferCount = initialBufferCount; } bufferPoolList.Add(new BufferPool(bufferSize, bufferCount)); this.remainingMemory -= (long)bufferCount * bufferSize; if (bufferSize >= maxBufferSize) { break; } long newBufferSizeLong = (long)bufferSize * 2; if (newBufferSizeLong > (long)maxBufferSize) { bufferSize = maxBufferSize; } else { bufferSize = (int)newBufferSizeLong; } } this.bufferPools = bufferPoolList.ToArray(); this.bufferSizes = new int[bufferPools.Length]; for (int i = 0; i < bufferPools.Length; i++) { this.bufferSizes[i] = bufferPools[i].BufferSize; } } public override void Clear() { for (int i = 0; i < this.bufferPools.Length; i++) { BufferPool bufferPool = this.bufferPools[i]; bufferPool.Clear(); } } void ChangeQuota(ref BufferPool bufferPool, int delta) { BufferPool oldBufferPool = bufferPool; int newLimit = oldBufferPool.Limit + delta; BufferPool newBufferPool = new BufferPool(oldBufferPool.BufferSize, newLimit); for (int i = 0; i < newLimit; i++) { byte[] buffer = oldBufferPool.Take(); if (buffer == null) { break; } newBufferPool.Return(buffer); newBufferPool.IncrementCount(); } this.remainingMemory -= oldBufferPool.BufferSize * delta; bufferPool = newBufferPool; } void DecreaseQuota(ref BufferPool bufferPool) { ChangeQuota(ref bufferPool, -1); } int FindMostExcessivePool() { long maxBytesInExcess = 0; int index = -1; for (int i = 0; i < this.bufferPools.Length; i++) { BufferPool bufferPool = this.bufferPools[i]; if (bufferPool.Peak < bufferPool.Limit) { long bytesInExcess = (bufferPool.Limit - bufferPool.Peak) * (long)bufferPool.BufferSize; if (bytesInExcess > maxBytesInExcess) { index = i; maxBytesInExcess = bytesInExcess; } } } return index; } int FindMostStarvedPool() { long maxBytesMissed = 0; int index = -1; for (int i = 0; i < this.bufferPools.Length; i++) { BufferPool bufferPool = this.bufferPools[i]; if (bufferPool.Peak == bufferPool.Limit) { long bytesMissed = bufferPool.Misses * (long)bufferPool.BufferSize; if (bytesMissed > maxBytesMissed) { index = i; maxBytesMissed = bytesMissed; } } } return index; } BufferPool FindPool(int desiredBufferSize) { for (int i = 0; i < this.bufferSizes.Length; i++) { if (desiredBufferSize <= this.bufferSizes[i]) { return this.bufferPools[i]; } } return null; } void IncreaseQuota(ref BufferPool bufferPool) { ChangeQuota(ref bufferPool, 1); } public override void ReturnBuffer(byte[] buffer) { Fx.Assert(buffer != null, "caller must verify"); BufferPool bufferPool = FindPool(buffer.Length); if (bufferPool != null) { if (buffer.Length != bufferPool.BufferSize) { throw Fx.Exception.Argument("buffer", SRCore.BufferIsNotRightSizeForBufferManager); } if (bufferPool.Return(buffer)) { bufferPool.IncrementCount(); } } } public override byte[] TakeBuffer(int bufferSize) { Fx.Assert(bufferSize >= 0, "caller must ensure a non-negative argument"); BufferPool bufferPool = FindPool(bufferSize); if (bufferPool != null) { byte[] buffer = bufferPool.Take(); if (buffer != null) { bufferPool.DecrementCount(); return buffer; } if (bufferPool.Peak == bufferPool.Limit) { bufferPool.Misses++; if (++totalMisses >= maxMissesBeforeTuning) { TuneQuotas(); } } return Fx.AllocateByteArray(bufferPool.BufferSize); } else { return Fx.AllocateByteArray(bufferSize); } } void TuneQuotas() { if (this.areQuotasBeingTuned) { return; } bool lockHeld = false; try { Monitor.TryEnter(this.tuningLock, ref lockHeld); // Don't bother if another thread already has the lock if (!lockHeld || this.areQuotasBeingTuned) { return; } this.areQuotasBeingTuned = true; } finally { if (lockHeld) { Monitor.Exit(this.tuningLock); } } // find the "poorest" pool int starvedIndex = FindMostStarvedPool(); if (starvedIndex >= 0) { BufferPool starvedBufferPool = this.bufferPools[starvedIndex]; if (this.remainingMemory < starvedBufferPool.BufferSize) { // find the "richest" pool int excessiveIndex = FindMostExcessivePool(); if (excessiveIndex >= 0) { // steal from the richest DecreaseQuota(ref this.bufferPools[excessiveIndex]); } } if (this.remainingMemory >= starvedBufferPool.BufferSize) { // give to the poorest IncreaseQuota(ref this.bufferPools[starvedIndex]); } } // reset statistics for (int i = 0; i < this.bufferPools.Length; i++) { BufferPool bufferPool = this.bufferPools[i]; bufferPool.Misses = 0; } this.totalMisses = 0; this.areQuotasBeingTuned = false; } class BufferPool { int bufferSize; int count; int limit; int misses; int peak; SynchronizedPool pool; public BufferPool(int bufferSize, int limit) { this.pool = new SynchronizedPool (limit); this.bufferSize = bufferSize; this.limit = limit; } public int BufferSize { get { return this.bufferSize; } } public int Limit { get { return this.limit; } } public int Misses { get { return this.misses; } set { this.misses = value; } } public int Peak { get { return this.peak; } } public void Clear() { this.pool.Clear(); this.count = 0; } public void DecrementCount() { int newValue = this.count - 1; if (newValue >= 0) { this.count = newValue; } } public void IncrementCount() { int newValue = this.count + 1; if (newValue <= this.limit) { this.count = newValue; if (newValue > this.peak) { this.peak = newValue; } } } public bool Return(byte[] buffer) { return this.pool.Return(buffer); } public byte[] Take() { return this.pool.Take(); } } } class GCBufferManager : InternalBufferManager { static GCBufferManager value = new GCBufferManager(); GCBufferManager() { } public static GCBufferManager Value { get { return value; } } public override void Clear() { } public override byte[] TakeBuffer(int bufferSize) { return Fx.AllocateByteArray(bufferSize); } public override void ReturnBuffer(byte[] buffer) { // do nothing, GC will reclaim this buffer } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //--------------------------------------------------------------------------- namespace System.Runtime { using System; using System.Collections.Generic; using System.Threading; abstract class InternalBufferManager { protected InternalBufferManager() { } public abstract byte[] TakeBuffer(int bufferSize); public abstract void ReturnBuffer(byte[] buffer); public abstract void Clear(); public static InternalBufferManager Create(long maxBufferPoolSize, int maxBufferSize) { if (maxBufferPoolSize == 0) { return GCBufferManager.Value; } else { Fx.Assert(maxBufferPoolSize > 0 && maxBufferSize >= 0, "bad params, caller should verify"); return new PooledBufferManager(maxBufferPoolSize, maxBufferSize); } } class PooledBufferManager : InternalBufferManager { const int minBufferSize = 128; const int maxMissesBeforeTuning = 8; const int initialBufferCount = 1; readonly object tuningLock; int[] bufferSizes; BufferPool[] bufferPools; long memoryLimit; long remainingMemory; bool areQuotasBeingTuned; int totalMisses; public PooledBufferManager(long maxMemoryToPool, int maxBufferSize) { this.tuningLock = new object(); this.memoryLimit = maxMemoryToPool; this.remainingMemory = maxMemoryToPool; List bufferPoolList = new List (); for (int bufferSize = minBufferSize; ; ) { long bufferCountLong = this.remainingMemory / bufferSize; int bufferCount = bufferCountLong > int.MaxValue ? int.MaxValue : (int)bufferCountLong; if (bufferCount > initialBufferCount) { bufferCount = initialBufferCount; } bufferPoolList.Add(new BufferPool(bufferSize, bufferCount)); this.remainingMemory -= (long)bufferCount * bufferSize; if (bufferSize >= maxBufferSize) { break; } long newBufferSizeLong = (long)bufferSize * 2; if (newBufferSizeLong > (long)maxBufferSize) { bufferSize = maxBufferSize; } else { bufferSize = (int)newBufferSizeLong; } } this.bufferPools = bufferPoolList.ToArray(); this.bufferSizes = new int[bufferPools.Length]; for (int i = 0; i < bufferPools.Length; i++) { this.bufferSizes[i] = bufferPools[i].BufferSize; } } public override void Clear() { for (int i = 0; i < this.bufferPools.Length; i++) { BufferPool bufferPool = this.bufferPools[i]; bufferPool.Clear(); } } void ChangeQuota(ref BufferPool bufferPool, int delta) { BufferPool oldBufferPool = bufferPool; int newLimit = oldBufferPool.Limit + delta; BufferPool newBufferPool = new BufferPool(oldBufferPool.BufferSize, newLimit); for (int i = 0; i < newLimit; i++) { byte[] buffer = oldBufferPool.Take(); if (buffer == null) { break; } newBufferPool.Return(buffer); newBufferPool.IncrementCount(); } this.remainingMemory -= oldBufferPool.BufferSize * delta; bufferPool = newBufferPool; } void DecreaseQuota(ref BufferPool bufferPool) { ChangeQuota(ref bufferPool, -1); } int FindMostExcessivePool() { long maxBytesInExcess = 0; int index = -1; for (int i = 0; i < this.bufferPools.Length; i++) { BufferPool bufferPool = this.bufferPools[i]; if (bufferPool.Peak < bufferPool.Limit) { long bytesInExcess = (bufferPool.Limit - bufferPool.Peak) * (long)bufferPool.BufferSize; if (bytesInExcess > maxBytesInExcess) { index = i; maxBytesInExcess = bytesInExcess; } } } return index; } int FindMostStarvedPool() { long maxBytesMissed = 0; int index = -1; for (int i = 0; i < this.bufferPools.Length; i++) { BufferPool bufferPool = this.bufferPools[i]; if (bufferPool.Peak == bufferPool.Limit) { long bytesMissed = bufferPool.Misses * (long)bufferPool.BufferSize; if (bytesMissed > maxBytesMissed) { index = i; maxBytesMissed = bytesMissed; } } } return index; } BufferPool FindPool(int desiredBufferSize) { for (int i = 0; i < this.bufferSizes.Length; i++) { if (desiredBufferSize <= this.bufferSizes[i]) { return this.bufferPools[i]; } } return null; } void IncreaseQuota(ref BufferPool bufferPool) { ChangeQuota(ref bufferPool, 1); } public override void ReturnBuffer(byte[] buffer) { Fx.Assert(buffer != null, "caller must verify"); BufferPool bufferPool = FindPool(buffer.Length); if (bufferPool != null) { if (buffer.Length != bufferPool.BufferSize) { throw Fx.Exception.Argument("buffer", SRCore.BufferIsNotRightSizeForBufferManager); } if (bufferPool.Return(buffer)) { bufferPool.IncrementCount(); } } } public override byte[] TakeBuffer(int bufferSize) { Fx.Assert(bufferSize >= 0, "caller must ensure a non-negative argument"); BufferPool bufferPool = FindPool(bufferSize); if (bufferPool != null) { byte[] buffer = bufferPool.Take(); if (buffer != null) { bufferPool.DecrementCount(); return buffer; } if (bufferPool.Peak == bufferPool.Limit) { bufferPool.Misses++; if (++totalMisses >= maxMissesBeforeTuning) { TuneQuotas(); } } return Fx.AllocateByteArray(bufferPool.BufferSize); } else { return Fx.AllocateByteArray(bufferSize); } } void TuneQuotas() { if (this.areQuotasBeingTuned) { return; } bool lockHeld = false; try { Monitor.TryEnter(this.tuningLock, ref lockHeld); // Don't bother if another thread already has the lock if (!lockHeld || this.areQuotasBeingTuned) { return; } this.areQuotasBeingTuned = true; } finally { if (lockHeld) { Monitor.Exit(this.tuningLock); } } // find the "poorest" pool int starvedIndex = FindMostStarvedPool(); if (starvedIndex >= 0) { BufferPool starvedBufferPool = this.bufferPools[starvedIndex]; if (this.remainingMemory < starvedBufferPool.BufferSize) { // find the "richest" pool int excessiveIndex = FindMostExcessivePool(); if (excessiveIndex >= 0) { // steal from the richest DecreaseQuota(ref this.bufferPools[excessiveIndex]); } } if (this.remainingMemory >= starvedBufferPool.BufferSize) { // give to the poorest IncreaseQuota(ref this.bufferPools[starvedIndex]); } } // reset statistics for (int i = 0; i < this.bufferPools.Length; i++) { BufferPool bufferPool = this.bufferPools[i]; bufferPool.Misses = 0; } this.totalMisses = 0; this.areQuotasBeingTuned = false; } class BufferPool { int bufferSize; int count; int limit; int misses; int peak; SynchronizedPool pool; public BufferPool(int bufferSize, int limit) { this.pool = new SynchronizedPool (limit); this.bufferSize = bufferSize; this.limit = limit; } public int BufferSize { get { return this.bufferSize; } } public int Limit { get { return this.limit; } } public int Misses { get { return this.misses; } set { this.misses = value; } } public int Peak { get { return this.peak; } } public void Clear() { this.pool.Clear(); this.count = 0; } public void DecrementCount() { int newValue = this.count - 1; if (newValue >= 0) { this.count = newValue; } } public void IncrementCount() { int newValue = this.count + 1; if (newValue <= this.limit) { this.count = newValue; if (newValue > this.peak) { this.peak = newValue; } } } public bool Return(byte[] buffer) { return this.pool.Return(buffer); } public byte[] Take() { return this.pool.Take(); } } } class GCBufferManager : InternalBufferManager { static GCBufferManager value = new GCBufferManager(); GCBufferManager() { } public static GCBufferManager Value { get { return value; } } public override void Clear() { } public override byte[] TakeBuffer(int bufferSize) { return Fx.AllocateByteArray(bufferSize); } public override void ReturnBuffer(byte[] buffer) { // do nothing, GC will reclaim this buffer } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- HandleCollector.cs
- XmlSchemaComplexContentRestriction.cs
- LightweightEntityWrapper.cs
- MobileUserControl.cs
- ApplicationContext.cs
- ConditionalExpression.cs
- UICuesEvent.cs
- ThreadStateException.cs
- SimpleApplicationHost.cs
- OdbcParameter.cs
- ReadContentAsBinaryHelper.cs
- BlockCollection.cs
- Listbox.cs
- EventNotify.cs
- SystemWebSectionGroup.cs
- DataGridTextBoxColumn.cs
- X509ThumbprintKeyIdentifierClause.cs
- _FtpDataStream.cs
- HttpPostProtocolReflector.cs
- DataGridViewCheckBoxCell.cs
- FrameworkElementAutomationPeer.cs
- LinkTarget.cs
- ColorBlend.cs
- MailAddress.cs
- DataGridViewCheckBoxColumn.cs
- QilTargetType.cs
- ClientScriptManager.cs
- PropertyInformationCollection.cs
- NetworkInterface.cs
- RSAPKCS1KeyExchangeFormatter.cs
- Binding.cs
- ConfigurationConverterBase.cs
- SerializationTrace.cs
- ListViewInsertionMark.cs
- ServiceModelInstallComponent.cs
- TraceContextEventArgs.cs
- PauseStoryboard.cs
- DeviceContext.cs
- EmbossBitmapEffect.cs
- ProfessionalColorTable.cs
- odbcmetadatacollectionnames.cs
- CatalogPartChrome.cs
- EntityFunctions.cs
- ToolStripDropDownButton.cs
- BaseDataList.cs
- Descriptor.cs
- Privilege.cs
- IBuiltInEvidence.cs
- ICspAsymmetricAlgorithm.cs
- MissingSatelliteAssemblyException.cs
- RadioButtonRenderer.cs
- TableLayoutPanel.cs
- LassoSelectionBehavior.cs
- userdatakeys.cs
- StorageAssociationTypeMapping.cs
- FixedBufferAttribute.cs
- MaterialGroup.cs
- OpenTypeCommon.cs
- ProvideValueServiceProvider.cs
- EFAssociationProvider.cs
- FindCriteriaElement.cs
- TypefaceMap.cs
- ElementHost.cs
- CTreeGenerator.cs
- TextEditorLists.cs
- CharUnicodeInfo.cs
- RecipientInfo.cs
- DefaultValueTypeConverter.cs
- Span.cs
- ResourceReferenceKeyNotFoundException.cs
- FloaterParaClient.cs
- HtmlHistory.cs
- IList.cs
- PropertyItemInternal.cs
- ListViewSelectEventArgs.cs
- AppModelKnownContentFactory.cs
- DiscoveryMessageProperty.cs
- TypeNameHelper.cs
- FigureHelper.cs
- ListBoxItemAutomationPeer.cs
- ProfileSettings.cs
- TouchDevice.cs
- SecurityChannelFactory.cs
- HttpValueCollection.cs
- ObjectTypeMapping.cs
- HtmlElementErrorEventArgs.cs
- LinqDataSourceValidationException.cs
- UnsafeNativeMethodsMilCoreApi.cs
- CellIdBoolean.cs
- safelink.cs
- MailAddressCollection.cs
- AssociationTypeEmitter.cs
- BufferBuilder.cs
- ObjectToModelValueConverter.cs
- HeaderUtility.cs
- WindowsRichEdit.cs
- SmiContextFactory.cs
- SqlSupersetValidator.cs
- TextBox.cs
- ObjectItemCollection.cs