在对低延迟网络进行一些基本的谷歌搜索之后,我提出了以下程序员和系统设计人员在开始低延迟网络时应该考虑的事项:
必须一起考虑硬件,系统和协议的设计
使用UDP而不是TCP开发协议并实现简单的ack-nak,在应用程序级别重新发送逻辑
减少消耗数据并从网络中打包数据的进程或线程的上下文切换次数(最好为零)
使用OS的最佳选择器(选择,kqueue,epoll等)
使用具有大量板载缓冲区(fifo)的高质量NIC和交换机
使用多个网卡,专门用于下游和上传数据流
减少其他设备或软件生成的IRQ数量(如果不需要,请简短删除)
减少互斥锁和条件的使用。而是尽可能使用无锁编程技术。利用架构的CAS功能。 (无锁容器)
考虑单线程多线程设计 - 上下文切换非常昂贵。
了解并正确使用架构的缓存系统(L1 / L2,RAM等)
希望完全控制内存管理,而不是委托给垃圾收集器
使用优质电缆,尽量缩短电缆长度,减少扭曲和卷曲次数
我的问题:我想知道在开始使用低延迟网络时,SOers认为其他什么是重要的。
随意批评以上任何一点
答案 0 :(得分:8)
电缆质量通常是类型的红鲱鱼。我想更多关于连接网络分析仪,看看你是否得到足够的重新传输来关心。如果你变得非常多,请尝试隔离它们发生的位置,并更换导致问题的电缆。如果您没有收到导致重新传输的错误,那么电缆(实质上)对延迟没有任何影响。
NIC和(特别是)交换机上的大缓冲区本身不会减少延迟。事实上,为了真正减少延迟,您通常希望使用最小的缓冲区,而不是更大的缓冲区。坐在缓冲区中而不是立即处理的数据会增加延迟。说实话,它很少值得担心,但仍然如此。如果确实希望最大限度地减少延迟(并且更少关注带宽),那么最好使用集线器而不是交换机(很难再找到,但肯定是低延迟,只要网络拥塞程度足够低。)
多个NIC可以帮助带宽很多,但它们对延迟的影响通常非常小。
编辑:然而,我的主要建议是获得规模感。通过一英尺减少网络电缆可以节省大约一纳秒的时间 - 与通过几种汇编语言指令加速数据包处理的顺序相同。
结论:与任何其他优化一样,为了获得更远的距离,您需要先测量延迟的位置,然后才能减少延迟。在大多数情况下,减少电线长度(使用一个示例)不会产生足够的差异,只是因为它开始很快。如果事情开始需要10微秒,那么你所能做的就是加速它超过10微秒,所以除非你的事情如此之快以至于10美元占你时间的很大一部分,否则不值得攻击。
答案 1 :(得分:6)
其他:
1:使用userland网络堆栈
2:与处理代码(共享缓存)相同的套接字上的服务中断
3:更喜欢固定长度协议,即使它们的字节数稍大(解析速度更快)
4:忽略网络字节顺序约定,只使用本机排序
5:从不在例程和对象池中分配(特别是垃圾收集语言)
6:尝试尽可能地防止字节复制(TCP发送困难)
7:使用直通切换模式
8:破解网络堆栈以删除TCP慢启动
9:宣传一个巨大的TCP窗口(但不要使用它),这样另一方可以一次拥有大量的机上数据包
10:关闭网卡合并,尤其是发送(如果需要,可以在应用堆栈中打包)
11:偏铜而不是光学我可以坚持下去,但这应该让人们思考
我不同意的一个:
1:网络电缆很少出现问题,除非出现问题(电缆类型有例外)
答案 2 :(得分:3)
这可能有点明显,但这是一种我很满意的技术,它适用于UDP和TCP,所以我会写一下:
1)永远不要排队大量的传出数据:具体来说,尽量避免将内存中的数据结构编组为序列化字节缓冲区,直到最后一刻。相反,当您的发送套接字select()s为ready-for-write时,在此时展平相关/脏数据结构的当前状态,并立即发送()它们。这样,数据永远不会在发送端“建立”。 (另外,请务必将套接字的SO_SNDBUF设置为尽可能小,以尽量减少内核中的数据排队)
2)你可以在接收端做类似的事情,假设你的数据以某种方式被锁定:你可以读取所有可用的数据消息,而不仅仅是读取数据消息将它们放入一个键控数据结构(例如一个哈希表),直到套接字没有更多的数据可供读取,然后(然后)迭代数据结构并处理数据。这样做的好处是,如果您的接收客户端必须对接收到的数据进行任何非平凡的处理,那么将自动/隐式地丢弃过时的传入消息(因为它们的替换将在密钥数据结构中覆盖它们),因此传入的数据包赢了不要在内核的传入消息队列中备份。 (当然,你可以让内核的队列填满并丢弃数据包,但是你的程序最终会读取'旧'数据包并删除'较新'数据包,这通常不是你想要的)。作为进一步的优化,您可以让I / O线程将键控数据结构交给单独的处理线程,这样I / O就不会被处理所阻止。