2011-03-08 61 views
2

我的C#程序通过多个套接字接收大量数据,看起来我有问题,Windows内核上的TCP缓存越来越重。
这可以通过从来自服务器的tcpdump的下列结果可以看出:
缓存网络流

18:02:18.963370 IP XXXX> yyyy.zzz: ack 10017011 win 0

您将使用哪种数据结构/策略来缓存读取数据以避免C#上的重载?
我目前正在为每个读取记录后调用的单独线程中的每个套接字使用一个委托,但这似乎是一个问题,因此我可能需要将其分成两个线程。
或者我应该看看在Windows端调整TCP参数?我正在使用Windows 7.
是否有任何有关内核优化的书籍?
我真的觉得程序变慢了,即使整个机器的负载是20-25%,而最高负载的核心的负载是50-60%。

+1

与http://stackoverflow.com/questions/5234277/c-1-socket-client-continous-data/5234427非常相似。我会在你的情况下推荐相同的东西。 – 2011-03-08 20:46:23

+0

是的 - 的确如此。我仍然感到惊讶的是,除了对手方的tcpdump之外,没有一个TCP堆栈重载的实际指标。即使应用程序本身在Windows中查看性能监视器时看起来很健康,它显然也是瓶颈。 – weismat 2011-03-09 05:09:20

回答

4

不知道你的程序架构太多,我猜你的程序本身就是瓶颈。如果您的应用程序不使用后台工作程序来收集TCP消息并将其存储为执行“繁重”操作的代码,那么您的程序正在读取现有缓冲区,然后处理TCP缓冲区重新填充。这种恶性循环只能有一个结局;最终缓冲区会在等待程序完成上一次处理时溢出。

我会重新考虑将TCP接收重构为ETL类型的模型。您需要一个线程,其工作是侦听TCP输入,从缓冲区中提取数据并将其排入集合,该集合对程序的其余部分可见。除了将数据从缓冲区中抽出并将原始消息移入此队列之外,它不应该做任何其他操作,并且应该尽可能快地完成此操作。

随着收到的消息在内存中,您的程序的其余部分可能会花费几乎一样长,因为它要消耗每条消息。你仍然必须确保你不会超载这个内存队列,但是作为一个单独的.NET对象可以引用高达2GB的内存,你不太可能遇到麻烦。如果你正在溢出这个程序中的队列,你需要考虑使处理更有效率,或者在这个过程的第二阶段抛出更多的线程。

+0

该程序通常不会崩溃,但服务器偶尔断开连接。当前的架构每个套接字都有一个线程,每个项目都有一个委托 - 我想我需要测试几种缓存方式,但阻塞集合听起来像是一个可行的候选方案。如果解析/解压缩需要成为读者线程的一部分,则取决于一点。感谢您的建议。 – weismat 2011-03-09 04:47:18

+0

经过一些测试后,我最终处理了一个带有字节数组,偏移量和使用长度的共享对象。我试着共享一个内存流集合,但开销看起来太大了(在几次内存异常之后)。 – weismat 2011-03-09 10:47:20