sockets - C# byte [] 操作 - 我应该使用 ArrayPool 还是 MemoryPool?
问题描述
我正在编写一个服务器应用程序。它接受数千个传入的套接字连接,每个连接都发送和接收消息。
每次通过套接字接收或发送消息时,我都会分配新的byte[] 缓冲区,然后它们会被垃圾收集:
byte[] receivingBuffer = new byte[bufferSize];
为了提高性能,我想重用byte[] buffers。我应该使用ArrayPool还是MemoryPool?
或者我应该创建一个固定长度的 byte[] 缓冲区的ObjectPool吗?例如,如果我发送和接收的消息从不超过 100 KB,那么我创建一个100 KB byte[] 缓冲区的ObjectPool。每次我需要发送或接收消息时,我都会得到其中一个缓冲区。
解决方案
做了一些研究和测试。ArrayPool 是正确使用的东西,它将显着提高性能。
class Program
{
private static ManualResetEvent m_event = new ManualResetEvent(false);
private static DateTime m_dtStart;
private static int m_iNumOfIterations = 0;
private static int m_iNumOfExceptions = 0;
private static double m_dAvgSizeRatio = 0;
private static object m_lock = new object();
private static void ReportSizeRatio(double dRatio)
{
lock (m_lock)
{
m_dAvgSizeRatio = (m_dAvgSizeRatio * m_iNumOfIterations + dRatio) / (m_iNumOfIterations + 1);
m_iNumOfIterations++;
}
}
/// <summary>
/// When using ArrayPool:
/// - CPU: 1 ~ 1.5%
/// - Memory: 67 MB
/// - Speed: 9130 runs/sec
/// - Given buffer is 1.56 times bigger than asked for.
///
/// When NOT using ArrayPool:
/// - CPU: 20 ~ 25%
/// - Memory: 500 ~ 1000 MB
/// - Speed: 5300 runs/sec
///
/// Conclusion: huge improvement in performance.
/// </summary>
/// <param name="obj"></param>
private static void Test(object obj)
{
TrueRandom random = new TrueRandom(500, 800);
m_event.WaitOne();
while (true)
{
int iDesiredSize = random.GetRandomInteger() * 1000;
byte[] buffer = null;
try
{
//buffer = ArrayPool<byte>.Shared.Rent(iDesiredSize);
buffer = new byte[iDesiredSize];
ReportSizeRatio((double)buffer.Length / (double)iDesiredSize);
}
catch
{
Interlocked.Increment(ref m_iNumOfExceptions);
}
Thread.Sleep(100);
//ArrayPool<byte>.Shared.Return(buffer);
}
}
static void Main(string[] args)
{
for (int i = 0; i < 1000; i++)
{
Thread thread = new Thread(Test);
thread.Start();
}
Console.WriteLine("All threads fired.");
m_dtStart = DateTime.Now;
m_event.Set();
while (true)
{
Thread.Sleep(1000);
Console.Clear();
Console.WriteLine($"Iterations/sec: { (int)(m_iNumOfIterations / (DateTime.Now - m_dtStart).TotalSeconds) }, Ave rented size: { (m_dAvgSizeRatio * 100d).ToString("0.0") }%, exceptions: { m_iNumOfExceptions }.");
}
}
}
推荐阅读
- python - JSONField 嵌套表示的序列化器
- plsql - 在 PL/SQL 中不使用 TO_CHAR 将整数连接到字符串
- c# - 如何将 xamarin 标签隐藏到属性或其他内容
- bash - Bash 脚本未在 .lua 上执行,退出状态 7(参数列表太长)
- javascript - 无法以角度过滤日期
- azure - 横向扩展 azure 应用服务与容器
- python - python中的分层采样,有约束
- javascript - 使用 vanilla Javascript 从选定的单选按钮中选择下一个/上一个单选按钮
- python - DQN 在不同的计算机上表现不同
- javascript - 如何在特定索引处的 DOM 字段对象中输入字符?