我有一台服务器和一台客户端。它们在不同的服务器上工作。两台服务器都有两个1000M网络适配器。
我在服务器和客户端都使用 tcp阻塞套接字。
接受套接字后,将启动一个新线程来处理请求。它的工作方式如下:
while(1) {
recv(); /* receive a char */
send(); /* send a line */
}
客户端只需向服务器发送一个字符,服务器就会向客户端发送一行文本。文本的长度约为200。
该行已预先加载到内存中。
客户端使用不同的线程连接到服务器。连接后,它将像:
while(1) {
send(); /* send a char */
recv(); /* receive a line and */
}
当我在客户端使用100个线程时(结果几乎相同),我在服务器中获得此网络流量:
tsar -l -i 1 --traffic
结果:
Time -------------traffic------------
Time bytin bytout pktin pktout
06/09/14-23:12:56 0.00 0.00 0.00 0.00
06/09/14-23:12:57 63.4M 155.3M 954.6K 954.6K
06/09/14-23:12:58 0.00 0.00 0.00 0.00
06/09/14-23:12:59 60.1M 147.3M 905.4K 905.4K
06/09/14-23:13:00 0.00 0.00 0.00 0.00
06/09/14-23:13:01 57.5M 140.8M 866.5K 866.4K
和sar -n DEV 1
:
11:20:46 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s
11:20:47 PM lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00
11:20:47 PM eth0 478215.05 478217.20 31756.46 77744.95 0.00 0.00 0.00
11:20:47 PM eth1 484318.28 484318.28 32162.05 78724.16 0.00 0.00 1.08
11:20:47 PM bond0 962533.33 962535.48 63918.51 156469.11 0.00 0.00 1.08
理论上,(bytin + bytout)
的最大值可以是256M
。我该如何存档?
任何帮助都会很棒,谢谢。
答案 0 :(得分:4)
实际上,在几个层中存在一些开销。 1Gbits / sec以太网在应用程序方面并不意味着那么多(但我估计最多90%)。经验法则是send
或recv
相当大的数据大小(例如至少几千字节)。发送或接收几百个字节是低效的。问题肯定是操作系统特定的(我在想Linux)。
回想一下,根据定义,TCP不是数据包的传输,而是字节流。阅读TCP wikipage。你应该避免send
- 或recv
- 几个字节,甚至一百个字节。每次尝试send
数千个字节。当然,接收方上的单个recv
(通常)不对应于发射器侧的单个send
,反之亦然(特别是如果您在发送和接收计算机之间有一些路由器;路由器;可以拆分或合并网络数据包,因此您无法确保在发射器中每个recv
的接收器上有一个send
。
Gigabit Ethernet希望Jumbo Frames接近9000字节。您可能希望send
的数据缓冲区略低于此值(因为IP和TCP的各种开销),所以请尝试8K字节。
send(2)手册页提到tcp(7)的MSG_MORE
标记。你可以小心使用它。另请参阅this。
syscalls(2)还有一些开销。我很惊讶你能够每秒赚到一百万。这个开销是另外一个原因是缓存大量的传出和传入数据(例如每个8192,16384或32768字节;你需要进行基准测试才能找到最好的数据)。如果内核更喜欢页面对齐的数据,我也不会感到惊讶。所以也许尝试让你的缓冲区对齐到4096字节(例如使用mmap(2)或posix_memalign(3) ...)
如果您关心性能,请不要将send(2)用于小字节数。至少更改您的应用程序,以便在每个send
系统调用时发送超过几千字节(例如4K字节)。对于recv(2),传递至少4千字节的缓冲区。因此send
或recv
单个字节或一百个字节的行是低效的。您的应用程序应缓冲此类数据(并可能将数据拆分为“应用程序消息”...)。有些库正在这样做(比如0MQ ...),或者至少使用分隔符(也许是换行符)终止每条消息,这样可以简化将接收缓冲区拆分为几个传入的应用程序消息。
我的感觉是你的应用程序效率低下且有问题(可能在其他网络上运行不好,例如两台计算机之间有一些路由器)。您需要重新设计并重新编写应用程序的某些部分!您需要缓冲,并且需要管理应用程序消息 - 拆分和连接它们....
Yous应该在多个网络上测试您的应用程序,特别是通过ADSL和wifi以及可能的远程网络(然后您会发现send
和recv
不匹配“)。
答案 1 :(得分:2)
根据我的数学,你相对接近饱和链接。
据我所知,这是流量的一秒。
Time -------------traffic------------ Time bytin bytout pktin pktout 06/09/14-23:12:57 63.4M 155.3M 954.6K 954.6K
通过以太网发送的TCP数据包有82字节的开销(42个以太网,20个IP,20个TCP),因此接收的数据量为(954.6k * 80 + 63.4M)* 8位,总计1.1G。
我认为对于如此大量的数据包,物理介质的协商会涉及额外的开销。由于链路利用率约为50%,如果有一个额外的延迟小到(1s / 954.6k)* 50%= 500 ns(半个微秒!),那么你已经考虑了额外的延迟。 500 ns是光线行进150米所需的时间,这并不是那么远。