BufferManager的实际用例

Eug*_*sky 5 .net buffer-manager

试图找到OutOfMemoryException的底部我发现WCF的缓冲TransferMode使用的.net的BufferManagers负责浪费数百兆字节(请参阅问题和我自己的答案如何防止我的WCF客户端中的BufferManager/PooledBufferManager应用程序浪费内存?有关详细信息以及如何通过简单地从"缓冲"切换到"流式传输"来解决它.

抛开WCF,BufferManagers被发明为一种比通常更好的替代方案:只需在需要时分配字节数组,并依赖GC清理它们并在引用超出范围后进行循环.

所以我的问题是:有没有人在真实世界的应用程序中使用BufferManagers,以便它在性能方面产生明显的差异,以证明必须手动的不便.清除()BufferManager(如果有必要)?

如果是这样,可以手动创建单个字节缓冲区并保持对它的引用没有解决该特定问题?

New*_*ion 3

我最近开发了一个代理服务,它接受多个客户端连接(最多 500 个同时连接)。代理将客户端请求中继到目标服务器,并将目标服务器的响应中继回客户端。代理服务使用字节数组 (Byte[]) 作为发送和接收数据的缓冲区。我没有适当的缓冲区管理器。

\n\n

代理每次都会创建一个新的字节数组以从套接字发送和接收数据。资源监视器中的私有字节不断增加。运行 ANT Memory Profiler 工具显示出不断增加的大碎片。

\n\n

解决方案是实现一个简单的 Buffermanager 类来管理缓冲区使用的内存。这是代码片段

\n\n
public class BufferManager\n    {\n        private readonly int m_ByteSize;\n\n        private readonly Stack<byte[]> m_Buffers;\n        private readonly object m_LockObject = new Object();\n\n        #region constructors\n\n        public BufferManager(int _byteSize, int _poolCount)\n        {\n            lock (m_LockObject)\n            {\n                m_ByteSize = _byteSize;\n                m_Buffers = new Stack<Byte[]>(_poolCount);  \n                for (int i = 0; i < _poolCount; i++)\n                {\n                    CreateNewSegment();\n                }\n            }\n        }\n\n        #endregion //constructors\n\n        public int AvailableBuffers\n        {\n            get { return m_Buffers.Count; }\n        }\n\n\n        public System.Int64 TotalBufferSizeInBytes\n        {\n            get { return m_Buffers.Count * m_ByteSize; }\n        }\n\n        public System.Int64 TotalBufferSizeInKBs\n        {\n            get { return (m_Buffers.Count * m_ByteSize/1000); }\n        }\n\n        public System.Int64 TotalBufferSizeInMBs\n        {\n            get { return (m_Buffers.Count * m_ByteSize/1000000); }\n        }\n\n\n\n        private void CreateNewSegment()\n        {\n            byte[] bytes = new byte[m_ByteSize];\n            m_Buffers.Push(bytes);\n        }\n\n\n\n        /// <summary>\n        /// Checks out a buffer from the manager\n        /// </summary>        \n        public Byte[] CheckOut()\n        {\n            lock (m_LockObject)\n            {\n                if (m_Buffers.Count == 0)\n                {\n                    CreateNewSegment();\n\n                }\n                return m_Buffers.Pop();\n            }\n        }\n\n\n        /// <summary>\n        /// Returns a buffer to the control of the manager\n        /// </summary>\n        ///<remarks>\n        /// It is the client\xe2\x80\x99s responsibility to return the buffer to the manger by\n        /// calling Checkin on the buffer\n        ///</remarks>\n        public void CheckIn(Byte[] _Buffer)\n        {\n            lock (m_LockObject)\n            {\n                m_Buffers.Push(_Buffer);\n            }\n        }\n\n\n    }\n
Run Code Online (Sandbox Code Playgroud)\n