我一直在分析TCP延迟(特别是write从一个小消息的用户空间到内核空间),以便对a的延迟有一些直觉write(确认这可能是特定于上下文的).我注意到测试之间存在很大的不一致,这对我来说似乎很相似,而且我很想知道差异来自何处.我知道微基准测试可能会有问题,但我仍然觉得我缺少一些基本的理解(因为延迟差异是~10倍).
设置是我有一个C++ TCP服务器接受一个客户端连接(来自同一CPU上的另一个进程),并且在与客户端连接时write,对套接字进行20次系统调用,一次发送一个字节.服务器的完整代码将在本文末尾复制.这是每次write使用的输出boost/timer(增加~1 mic的噪音):
$ clang++ -std=c++11 -stdlib=libc++ tcpServerStove.cpp -O3; ./a.out
18 mics
3 mics
3 mics
4 mics
3 mics
3 mics
4 mics
3 mics
5 mics
3 mics
...
Run Code Online (Sandbox Code Playgroud)
我可靠地发现第一个write明显慢于其他人.如果我write在计时器中包装10,000个呼叫,平均每个2微秒write,但第一个呼叫总是15个以上的话筒.为什么会出现这种"变暖"现象?
相关地,我运行了一个实验,在每个write调用之间我做一些阻止CPU工作(计算一个大的素数).这会导致所有的write调用是缓慢的:
$ clang++ -std=c++11 -stdlib=libc++ tcpServerStove.cpp -O3; ./a.out
20 mics
23 mics
23 mics
30 mics
23 mics
21 mics
21 mics
22 mics
22 …Run Code Online (Sandbox Code Playgroud) 根据http://www.solacesystems.com/blog/kernel-bypass-revving-up-linux-networking:
[...] 一个名为 OpenOnload 的网络驱动程序,它使用“内核绕过”技术在用户空间中一起运行应用程序和网络驱动程序,并且绕过内核。这允许连接的应用程序端以更低且更一致的延迟每秒处理更多消息。
[...]
如果您是一名开发人员或架构师,多年来一直在与上下文切换作斗争,那么内核绕过可能会让人感觉像是在作弊,但幸运的是,这完全符合规则。
执行这种内核绕过所需的功能是什么?