私は最近、複数のクライアント接続(最大500の同時接続)を受け入れたプロキシサービスを開発しました。プロキシは、クライアント要求を宛先サーバーに中継し、応答を宛先サーバーからクライアントに中継しました。プロキシサービスは、バイト配列(Byte [])をバッファとして使用してデータを送受信しました。 Buffer Managerはありませんでした。
プロキシがソケットからデータを送受信するたびに、新しいバイト配列を作成していました。リソースモニターのプライベートバイトは増加し続けました。 ANT Memory Profilerツールを実行すると、大きな断片が増え続けました。
解決策は、Buffersによって使用されるメモリを管理するための単純なBuffermanagerクラスを実装することでした。ここにコードスニペットがあります
public class BufferManager
{
private readonly int m_ByteSize;
private readonly Stack<byte[]> m_Buffers;
private readonly object m_LockObject = new Object();
#region constructors
public BufferManager(int _byteSize, int _poolCount)
{
lock (m_LockObject)
{
m_ByteSize = _byteSize;
m_Buffers = new Stack<Byte[]>(_poolCount);
for (int i = 0; i < _poolCount; i++)
{
CreateNewSegment();
}
}
}
#endregion //constructors
public int AvailableBuffers
{
get { return m_Buffers.Count; }
}
public System.Int64 TotalBufferSizeInBytes
{
get { return m_Buffers.Count * m_ByteSize; }
}
public System.Int64 TotalBufferSizeInKBs
{
get { return (m_Buffers.Count * m_ByteSize/1000); }
}
public System.Int64 TotalBufferSizeInMBs
{
get { return (m_Buffers.Count * m_ByteSize/1000000); }
}
private void CreateNewSegment()
{
byte[] bytes = new byte[m_ByteSize];
m_Buffers.Push(bytes);
}
/// <summary>
/// Checks out a buffer from the manager
/// </summary>
public Byte[] CheckOut()
{
lock (m_LockObject)
{
if (m_Buffers.Count == 0)
{
CreateNewSegment();
}
return m_Buffers.Pop();
}
}
/// <summary>
/// Returns a buffer to the control of the manager
/// </summary>
///<remarks>
/// It is the client’s responsibility to return the buffer to the manger by
/// calling Checkin on the buffer
///</remarks>
public void CheckIn(Byte[] _Buffer)
{
lock (m_LockObject)
{
m_Buffers.Push(_Buffer);
}
}
}
私は[私の話]([もみ)](http://msdn.microsoft.com/en-us/library/)についてさらに明確にするために私の質問を編集しました。 system.servicemodel.channels.buffermanager(v = vs.100).aspx)。私はあなたが自分自身を書いた理由をよく分かりません(そして、.netの実装について私の質問に答えるためにそれを使いました)。しかし、とにかく、あなたの実装が一度獲得したメモリを解放しないという事実を別にすれば、組み込みGCに仕事を任せているのはどのようなことでしょうか? –
2番目の段落には、プロファイラ結果が含まれています。 –