我正在构建一个套接字应用程序,它需要将许多小/中等大小的文件洗牌,类似于5-100kb大小的文件到很多不同的客户端(有点像Web服务器,但仍然不完全)。
我应该使用winsock(win32)中的标准poll / epoll(linux)或async套接字,还是有更多性能的方法(例如win32上的重叠i / o)?
Linux和Windows都是可能的平台!
答案 0 :(得分:3)
在Linux上,使用epoll
解复用多个套接字是通过TCP进行并行I / O的最快方式。
但我还要提到,为了便携性,(并且因为你似乎对Linux或Windows感兴趣),你应该研究Boost.Asio。它有一个可移植的API,但在Linux上使用epoll
,在Windows上使用重叠的I / O,因此您可以构建高效的和便携式网络应用程序。
此外,由于您正在使用文件,因此在执行I / O时还应实现双缓冲以获得最佳性能。换句话说,您使用两个缓冲区发送/ recv每个文件。例如,在发送端,您从磁盘读取到一个缓冲区然后通过网络发送该缓冲区,而另一个线程从磁盘读取下一个数据块到第二个缓冲区。这样,您可以将磁盘I / O与网络I / O重叠。
答案 1 :(得分:2)
在Linux上,sendfile()
是专门用于将数据从文件发送到套接字的高性能API(您仍然需要使用poll
进行多路复用,它只是{{1}的替代品} / read
部分)。
答案 2 :(得分:2)
除了epoll
之外,Linux sendfile(2)
似乎更适合您在服务器端的需求。
答案 3 :(得分:1)
在Windows上,您可以尝试使用TransmitFile,它有可能通过避免内核空间提高您的性能< - >用户空间数据复制。
答案 4 :(得分:0)
不幸的是,如果你想获得最大可能的性能,你仍然需要在Windows和Linux上手工制作你的I / O代码,因为目前可用的抽象库不能很好地扩展到多个线程(如果有的话)。 / p>
如果你想要可移植性(和易用性),Boost asio可能是最好的选择,但它在多线程可伸缩性方面确实有它的局限性(参见C++ Socket Server - Unable to saturate CPU) - 我想主要的问题是集成超时处理没有过多锁定到多线程事件循环。
基本上,您希望用于获得最佳性能的是I / O完成端口,其中包含Windows上的工作线程池和边缘触发的epoll以及Linux上的工作线程池。
答案 5 :(得分:0)
不要过早优化您的计划。
假设它不是一个过早的优化,最简单的方法就是将所有数据保存在内存中。你可以根据需要mmap(),或者只是在启动时加载它们。发送已经存在于内存中的东西是不费脑子的。
话虽如此,尝试用(例如)epoll复用很多东西可能有点令人头疼,你能不能使用已经写过的东西吗?