4

在对低延迟网络进行了一些基本的谷歌搜索之后,我提出了以下程序员和系统设计人员在着手进行低延迟网络时应该考虑的事项列表:

  1. 硬件、系统和协议的设计必须一起考虑

  2. 使用UDP代替TCP开发协议并实现简单的ack-nak,在应用层重发逻辑

  3. 减少消耗和打包数据的进程或线程的上下文切换次数(最好为零)

  4. 使用操作系统的最佳选择器(select、kqueue、epoll 等)

  5. 使用具有大量板载缓冲区 (fifo) 的优质 NIC 和交换机

  6. 使用多个 NIC,专门用于下游和上游数据流

  7. 减少其他设备或软件生成的 IRQ 数量(简而言之,如果不需要它们,请删除它们)

  8. 减少互斥量和条件的使用。而是尽可能使用无锁编程技术。利用架构的 CAS 功能。(无锁容器

  9. 考虑单线程而不是多线程设计 - 上下文切换非常昂贵。

  10. 了解并正确利用架构的缓存系统(L1/L2、RAM 等)

  11. 更喜欢完全控制内存管理,而不是委托给垃圾收集器

  12. 使用质量好的电缆,电缆尽可能的短,减少扭曲和卷曲的次数

我的问题:我想知道其他 SOers 认为在开始低延迟网络时还有哪些重要的事情。

随意批评以上任何一点

4

3 回答 3

8

电缆质量通常是一种红鲱鱼。我会更多地考虑连接网络分析仪,看看你是否有足够的重新传输来关心。如果您收到很多,请尝试隔离它们发生的位置,并更换导致问题的电缆。如果您没有收到导致重新传输的错误,那么电缆(实际上)对延迟没有影响。

NIC 和(尤其是)交换机上的大缓冲区本身不会减少延迟。事实上,为了真正减少延迟,您通常希望使用尽可能的缓冲区,而不是更大的缓冲区。位于缓冲区而不是立即处理的数据会增加延迟。说实话,这很少值得担心,但仍然如此。如果您真的想最大程度地减少延迟(并且不太关心带宽),那么最好使用集线器而不是交换机(现在很难找到,但只要网络拥塞足够低,延迟绝对是低的)。

多个 NIC 可以极大地帮助带宽,但它们对延迟的影响通常非常小。

编辑:然而,我的主要建议是获得规模感。减少一英尺的网络电缆可以为您节省大约一纳秒 - 与通过几个汇编语言指令加速数据包处理的一般顺序相同。

底线:与任何其他优化一样,要走得更远,您需要测量延迟的位置,然后才能采取很多措施来减少延迟。在大多数情况下,减少电线长度(举一个例子)不会引起足够的注意,仅仅是因为它开始很快。如果某件事开始需要 10 微秒,那么您无法将其加速超过 10 微秒,因此除非您的速度如此之快以至于 10 我们占您时间的很大一部分,否则不值得攻击。

于 2011-05-19T22:11:58.203 回答
6

其他:

1:使用用户态网络堆栈

2:与处理代码在同一个套接字上的服务中断(共享缓存)

3:更喜欢固定长度的协议,即使它们的字节稍大(更快的解析)

4:忽略网络字节顺序约定,只使用本机排序

5:永远不要在例程和对象池中分配(尤其是垃圾收集语言)

6:尽量防止字节复制(TCP发送中的hard)

7:使用直通切换模式

8:破解网络堆栈以消除 TCP 慢启动

9:通告一个巨大的 TCP 窗口(但不要使用它),以便对方一次可以有很多飞行数据包

10:关闭网卡合并,尤其是发送(如果需要,在应用程序堆栈中打包)

11:更喜欢铜而不是光学

我可以继续前进,但这应该让人们思考

一个我不同意的:

1:网线很少是问题,除非是坏了(在电缆类型方面有一个例外)

于 2011-08-02T04:25:48.697 回答
3

这可能有点明显,但这是一种我很满意的技术,它适用于 UDP 和 TCP,所以我会写一下:

1) 永远不要排队大量的传出数据:具体来说,尽量避免将内存中的数据结构编组到序列化字节缓冲区中,直到最后一刻。相反,当您的发送套接字选择()准备好写入时,将当时相关/脏数据结构的当前状态展平,并立即发送()它们。这样,数据将永远不会在发送端“堆积”。(另外,确保将套接字的 SO_SNDBUF 设置为尽可能小,以尽量减少内核内的数据排队)

2)您可以在接收端做类似的事情,假设您的数据以某种方式键入:而不是执行(读取数据消息,处理数据消息,重复)循环,您可以读取所有可用的数据消息并将它们放入一个键控数据结构(例如哈希表),直到套接字没有更多数据可供读取,然后(并且仅在那时)迭代数据结构并处理数据。这样做的好处是,如果您的接收客户端必须对接收到的数据进行任何重要的处理,那么过时的传入消息将被自动/隐式丢弃(因为它们的替换会在键控数据结构中覆盖它们),因此传入的数据包将获胜'不在内核的传入消息队列中备份。(当然,您可以让内核的队列填满并丢弃数据包,但是随后您的程序最终会读取“旧”数据包并丢弃“新”数据包,这通常不是您想要的)。作为进一步的优化,您可以让 I/O 线程将键控数据结构交给一个单独的处理线程,这样 I/O 就不会被处理耽搁。

于 2011-08-02T04:48:33.600 回答