实际上我开发了一个基于tcp的网络服务器,它可以执行大量的读写操作,并且对其业务逻辑使用小于零的CPU,它充当两个端点之间的桥接器。 网络服务器是为.NET 4.5开发的,它使用:
我的担忧与垃圾收集有关,事实上,据我所知,虽然我避免了内存碎片预分配我需要的所有缓冲区,垃圾收集器检查它们是否必须被收集,因为它们没有被分配到里面大堆。
会更好,而不是分配10.000字节[8192]会更好地分配一个大字节[81920000]并使用ArraySegment来使用切片?
谢谢。
我切换到服务器模式垃圾收集,似乎我的系统比以前工作得更好(实际上我能够在同一台机器上处理高达4GiB的流量与5000个客户端,这意味着10000个套接字)。 我将开始在更多机器上测试架构。
答案 0 :(得分:0)
您需要注意细分发送和接收数据的方式。当接收数据时,试图将任何缓冲器保持在LOH的最小值以下,即<80Kb。发送也一样。
另一种方法是创建一个固定大小的缓冲池,以便根据需要使用和回收。这样可以避免不断创建和破坏分配,从而避免出现任何内存碎片问题。
与大多数问题一样,最终选择取决于最终解决方案的最佳选择。通过使用小缓冲区可以更容易地避免碎片,但这也会带来相关的性能成本。
答案 1 :(得分:0)
当我开发基于SocketAsyncEventArgs
的高性能TCP服务器时,我遇到了类似“内存泄漏”的问题。
问题是当你使用缓冲区(byte[]
)它被固定时。所以GC实际上无法做任何事情。
我个人写了这个类(不完全是这个):
class Buffer
{
const int BUFFER_SIZE = 8 * 1024;
public Buffer()
{
InUse = false;
Bytes = new byte[BUFFER_SIZE];
}
public bool InUse { get; set; }
public byte[] Bytes { get; private set; }
}
另一个名为BufferPool
的类,其List<Buffer>
作为缓冲池(检测死连接和释放池等的逻辑在我的情况下是非常复杂的,所以我跳过内部)。
这样,您可以重用已分配的字节数组作为新操作的缓冲区。
我已经这样实现了,因为我无法限制最大连接数。如果您可以将连接数限制为特定的最大值,则this codeproject article可以提供帮助。
注意:我忘了说在这种情况下无法回收已分配的内存。
答案 2 :(得分:0)
简单情况下的客户端 - 服务器应用程序意味着 N 客户端和 1 服务器。每个客户端请求都应是独立的,并且独立于其他客户端的请求。这允许您使用 N 线程来支持 N 并发用户。
现在,线程不必使用共享资源。他们可以,但它会影响性能。即使您使用乐观(无锁)并发模型,这也不意味着线程不会竞争共享资源。
现在,如果每个线程都有一个单独的缓冲区,则每个线程都使用它自己的内存,并且不同的并发线程之间不存在竞争。如果您有许多用户,这将增加GC的内存碎片和CPU时间。
如果使用大型共享缓冲区,则会增加尝试访问不同线程的共享缓冲区所花费的时间。此外,您还将减少GC处理收集所花费的时间。
<小时/> 就个人而言,我只想在每个线程中使用1个小缓冲区。这有奖金: