Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / BufferManager.cs / 1 / BufferManager.cs
//---------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //--------------------------------------------------------------------------- namespace System.ServiceModel.Channels { using System; using System.ServiceModel; using System.Collections.Generic; using System.Threading; public abstract class BufferManager { public abstract byte[] TakeBuffer(int bufferSize); public abstract void ReturnBuffer(byte[] buffer); public abstract void Clear(); public static BufferManager CreateBufferManager(long maxBufferPoolSize, int maxBufferSize) { if (maxBufferPoolSize == 0) { return GCBufferManager.Value; } else { return new PooledBufferManager(maxBufferPoolSize, maxBufferSize); } } class PooledBufferManager : BufferManager { int[] bufferSizes; BufferPool[] bufferPools; object tuningLock = new object(); long memoryLimit; long remainingMemory; bool areQuotasBeingTuned; int totalMisses; const int minBufferSize = 128; const int maxMissesBeforeTuning = 8; const int initialBufferCount = 1; public PooledBufferManager(long maxMemoryToPool, int maxBufferSize) { if (maxMemoryToPool < 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("maxMemoryToPool", maxMemoryToPool, SR.GetString(SR.ValueMustBeNonNegative))); } if (maxBufferSize < 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("maxBufferSize", maxBufferSize, SR.GetString(SR.ValueMustBeNonNegative))); } memoryLimit = maxMemoryToPool; remainingMemory = maxMemoryToPool; ListbufferPoolList = new List (); for (int bufferSize = minBufferSize; ; ) { long bufferCountLong = remainingMemory / bufferSize; int bufferCount = bufferCountLong > int.MaxValue ? int.MaxValue : (int)bufferCountLong; if (bufferCount > initialBufferCount) bufferCount = initialBufferCount; bufferPoolList.Add(new BufferPool(bufferSize, bufferCount)); remainingMemory -= (long)bufferCount * bufferSize; if (bufferSize >= maxBufferSize) break; long newBufferSizeLong = (long)bufferSize * 2; if (newBufferSizeLong > (long)maxBufferSize) { bufferSize = maxBufferSize; } else { bufferSize = (int)newBufferSizeLong; } } bufferPools = bufferPoolList.ToArray(); bufferSizes = new int[bufferPools.Length]; for (int i = 0; i < bufferPools.Length; i++) { bufferSizes[i] = bufferPools[i].BufferSize; } } public override void Clear() { for (int i = 0; i < bufferPools.Length; i++) { BufferPool bufferPool = 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(); } 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 < bufferPools.Length; i++) { BufferPool bufferPool = 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 < bufferPools.Length; i++) { BufferPool bufferPool = 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 < bufferSizes.Length; i++) { if (desiredBufferSize <= bufferSizes[i]) { return bufferPools[i]; } } return null; } void IncreaseQuota(ref BufferPool bufferPool) { ChangeQuota(ref bufferPool, 1); } public override void ReturnBuffer(byte[] buffer) { if (buffer == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer"); BufferPool bufferPool = FindPool(buffer.Length); if (bufferPool != null) { if (buffer.Length != bufferPool.BufferSize) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.BufferIsNotRightSizeForBufferManager), "buffer")); } if (bufferPool.Return(buffer)) { bufferPool.IncrementCount(); } } } byte[] AllocNewBuffer(int bufferSize) { return DiagnosticUtility.Utility.AllocateByteArray(bufferSize); } public override byte[] TakeBuffer(int bufferSize) { if (bufferSize < 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("bufferSize", bufferSize, SR.GetString(SR.ValueMustBeNonNegative))); } 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 AllocNewBuffer(bufferPool.BufferSize); } else { return AllocNewBuffer(bufferSize); } } void TuneQuotas() { if (areQuotasBeingTuned) return; bool lockHeld = false; try { try { } finally { lockHeld = Monitor.TryEnter(tuningLock); } // Don't bother if another thread already has the lock if (!lockHeld || areQuotasBeingTuned) return; areQuotasBeingTuned = true; } finally { if (lockHeld) { Monitor.Exit(tuningLock); } } // find the "poorest" pool int starvedIndex = FindMostStarvedPool(); if (starvedIndex >= 0) { BufferPool starvedBufferPool = bufferPools[starvedIndex]; if (remainingMemory < starvedBufferPool.BufferSize) { // find the "richest" pool int excessiveIndex = FindMostExcessivePool(); if (excessiveIndex >= 0) { // steal from the richest DecreaseQuota(ref bufferPools[excessiveIndex]); } } if (remainingMemory >= starvedBufferPool.BufferSize) { // give to the poorest IncreaseQuota(ref bufferPools[starvedIndex]); } } // reset statistics for (int i = 0; i < bufferPools.Length; i++) { BufferPool bufferPool = bufferPools[i]; bufferPool.Misses = 0; } totalMisses = 0; areQuotasBeingTuned = false; } class BufferPool { int bufferSize; int count; int limit; int misses; int peak; SynchronizedPool pool; public BufferPool(int bufferSize, int limit) { pool = new SynchronizedPool (limit); this.bufferSize = bufferSize; this.limit = limit; } public int BufferSize { get { return bufferSize; } } public int Limit { get { return limit; } } public int Misses { get { return misses; } set { this.misses = value; } } public int Peak { get { return peak; } } public void Clear() { pool.Clear(); count = 0; } public void DecrementCount() { int newValue = count - 1; if (newValue >= 0) { count = newValue; } } public void IncrementCount() { int newValue = count + 1; if (newValue <= limit) { count = newValue; if (newValue > peak) { peak = newValue; } } } public bool Return(byte[] buffer) { return pool.Return(buffer); } public byte[] Take() { return pool.Take(); } } } class GCBufferManager : BufferManager { static GCBufferManager value = new GCBufferManager(); GCBufferManager() { } public static GCBufferManager Value { get { return value; } } public override void Clear() { } public override byte[] TakeBuffer(int bufferSize) { if (bufferSize < 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("bufferSize", bufferSize, SR.GetString(SR.ValueMustBeNonNegative))); } return DiagnosticUtility.Utility.AllocateByteArray(bufferSize); } public override void ReturnBuffer(byte[] buffer) { if (buffer == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("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.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CommandExpr.cs
- JavaScriptSerializer.cs
- ConfigXmlReader.cs
- PageAsyncTaskManager.cs
- SplitterEvent.cs
- FixedTextSelectionProcessor.cs
- IssuanceTokenProviderState.cs
- DesignSurfaceServiceContainer.cs
- ParseNumbers.cs
- EncryptedData.cs
- ComponentCodeDomSerializer.cs
- ManipulationVelocities.cs
- WMICapabilities.cs
- ConfigurationManagerInternal.cs
- UnknownWrapper.cs
- CharacterString.cs
- OdbcConnectionHandle.cs
- SequentialOutput.cs
- Enum.cs
- RequestStatusBarUpdateEventArgs.cs
- SelectedDatesCollection.cs
- Normalization.cs
- MoveSizeWinEventHandler.cs
- DataControlFieldCell.cs
- HwndSource.cs
- infer.cs
- Delegate.cs
- PolyBezierSegment.cs
- Tokenizer.cs
- CachedTypeface.cs
- ExplicitDiscriminatorMap.cs
- SafeCoTaskMem.cs
- COM2ExtendedTypeConverter.cs
- UiaCoreApi.cs
- Logging.cs
- RoutingChannelExtension.cs
- ShaderEffect.cs
- FloatMinMaxAggregationOperator.cs
- PriorityChain.cs
- GeometryDrawing.cs
- SrgsDocument.cs
- SystemFonts.cs
- RootBuilder.cs
- HwndSource.cs
- SafePointer.cs
- InfiniteIntConverter.cs
- ProtectedProviderSettings.cs
- BlurBitmapEffect.cs
- GridPatternIdentifiers.cs
- MasterPageParser.cs
- MiniMapControl.xaml.cs
- OletxDependentTransaction.cs
- Formatter.cs
- SafeArrayTypeMismatchException.cs
- ActivityPreviewDesigner.cs
- cache.cs
- Clipboard.cs
- WebPartActionVerb.cs
- GridViewSelectEventArgs.cs
- X509CertificateCollection.cs
- HttpSocketManager.cs
- FastEncoderStatics.cs
- TracingConnection.cs
- CodeDomSerializationProvider.cs
- HitTestWithPointDrawingContextWalker.cs
- StandardOleMarshalObject.cs
- DirectoryGroupQuery.cs
- SrgsItemList.cs
- _TLSstream.cs
- GifBitmapEncoder.cs
- RequiredFieldValidator.cs
- InfoCardTrace.cs
- IPPacketInformation.cs
- NotSupportedException.cs
- XsltQilFactory.cs
- OdbcConnectionStringbuilder.cs
- AsyncOperation.cs
- EnvelopedPkcs7.cs
- RefreshEventArgs.cs
- ByteFacetDescriptionElement.cs
- ConsoleEntryPoint.cs
- CodeObject.cs
- FontStyle.cs
- LineUtil.cs
- NoneExcludedImageIndexConverter.cs
- XmlWellformedWriter.cs
- NullableFloatAverageAggregationOperator.cs
- PermissionSetEnumerator.cs
- StorageEntityTypeMapping.cs
- HtmlEmptyTagControlBuilder.cs
- DataControlLinkButton.cs
- DynamicDocumentPaginator.cs
- ExtensionSimplifierMarkupObject.cs
- ClientType.cs
- PartialList.cs
- MetadataArtifactLoader.cs
- TransformPattern.cs
- ColumnTypeConverter.cs
- GlobalizationSection.cs
- SqlParameterCollection.cs