网络性能问题和缓慢的 tcp_write_xmit/tcp_ack 系统调用,在 OpenVZ 内核上有大量 save_stack 调用
Network performance issues and slow tcp_write_xmit/tcp_ack syscalls with a lot of save_stack calls on OpenVZ kernel
我 运行 在 Centos 上遇到网络性能不佳的问题。在具有 24 个内核和 Broadcom 5720 NIC 的戴尔服务器上的最新 OpenVZ RHEL7 内核(基于 3.10)上观察到该问题。无论是主机系统还是 OpenVZ 容器。服务器接收 RTMP 连接并将 RTMP 流转发给另一个消费者。读写不稳定,流会定期冻结几秒钟。
我已经开始使用 strace 和 perf 检查系统。 Strace 严重影响系统,似乎只有 perf 可能有帮助。我使用了启用了 debugfs 的 OpenVZ 调试内核。系统在交换进程中花费了太多时间(根据性能数据)。我已经为负载下的系统构建了火焰图(100 兆位数据,200 兆位输出)并且注意到内核在 tcp_write_xmit 和 tcp_ack 上花费了太多时间。在这些调用的顶部,我看到 save_stack 个系统调用。
另一方面,我在 Amazon EC2 实例(最新的 Amazon Linux AMI 2017.09)上测试了相同的场景,perf 没有跟踪此类问题。样本总量为 300000,系统根据 swapper 中的 perf 样本花费了 82% 的时间,但是 net_rx_action(以及随之而来的 tcp_write_xmit 和 tcp_ack)在 swapper 中只需要 1797 个样本(0.59样品总量的百分比)。在火焰图中的 net_rx_action 调用顶部,我没有看到任何与堆栈跟踪相关的调用。
OpenVZ 系统的输出看起来不同。在 1833152 个样本中,500892 个(27%)处于交换过程中,194289 个样本(10.5%)处于 net_rx_action.
完整的 svg of calls on vzkernel7 is here and svg of EC2 instance calls is here。您可以下载并在浏览器中打开以交互式查看火焰图。
所以,我想寻求帮助,我有几个问题。
- 为什么来自 EC2 实例的火焰图不像我的服务器那样包含那么多 save_stack 调用?
- perf 是强制系统调用 save_stack 还是某些内核设置?可以禁用吗?如何禁用?
- EC2 来宾上的 Xen 是否处理所有 tcp_ack 和其他系统调用?有没有可能是 EC2 服务器上的主机系统做了一些工作而来宾系统没有看到它?
感谢您的帮助。
我已经阅读了内核源代码并找到了我的问题的答案。
save_stack calls
是由Kernel Address Sanitizer feature that was enabled in OpenVZ debug kernel by CONFIG_KASAN
option. When this options is enabled, on each kmem_cache_free syscall kernel calls __cache_free
引起的
static inline void __cache_free(struct kmem_cache *cachep, void *objp,
unsigned long caller)
{
/* Put the object into the quarantine, don't touch it for now. */
if (kasan_slab_free(cachep, objp))
return;
___cache_free(cachep, objp, caller);
}
禁用 CONFIG_KASAN
kasan_slab_free 将响应 false
(检查 include/linux/kasan.h
)。 OpenVZ 调试内核 was built 与 CONFIG_KASAN=y
,Amazon AMI 不是。
我 运行 在 Centos 上遇到网络性能不佳的问题。在具有 24 个内核和 Broadcom 5720 NIC 的戴尔服务器上的最新 OpenVZ RHEL7 内核(基于 3.10)上观察到该问题。无论是主机系统还是 OpenVZ 容器。服务器接收 RTMP 连接并将 RTMP 流转发给另一个消费者。读写不稳定,流会定期冻结几秒钟。
我已经开始使用 strace 和 perf 检查系统。 Strace 严重影响系统,似乎只有 perf 可能有帮助。我使用了启用了 debugfs 的 OpenVZ 调试内核。系统在交换进程中花费了太多时间(根据性能数据)。我已经为负载下的系统构建了火焰图(100 兆位数据,200 兆位输出)并且注意到内核在 tcp_write_xmit 和 tcp_ack 上花费了太多时间。在这些调用的顶部,我看到 save_stack 个系统调用。
另一方面,我在 Amazon EC2 实例(最新的 Amazon Linux AMI 2017.09)上测试了相同的场景,perf 没有跟踪此类问题。样本总量为 300000,系统根据 swapper 中的 perf 样本花费了 82% 的时间,但是 net_rx_action(以及随之而来的 tcp_write_xmit 和 tcp_ack)在 swapper 中只需要 1797 个样本(0.59样品总量的百分比)。在火焰图中的 net_rx_action 调用顶部,我没有看到任何与堆栈跟踪相关的调用。
OpenVZ 系统的输出看起来不同。在 1833152 个样本中,500892 个(27%)处于交换过程中,194289 个样本(10.5%)处于 net_rx_action.
完整的 svg of calls on vzkernel7 is here and svg of EC2 instance calls is here。您可以下载并在浏览器中打开以交互式查看火焰图。
所以,我想寻求帮助,我有几个问题。
- 为什么来自 EC2 实例的火焰图不像我的服务器那样包含那么多 save_stack 调用?
- perf 是强制系统调用 save_stack 还是某些内核设置?可以禁用吗?如何禁用?
- EC2 来宾上的 Xen 是否处理所有 tcp_ack 和其他系统调用?有没有可能是 EC2 服务器上的主机系统做了一些工作而来宾系统没有看到它?
感谢您的帮助。
我已经阅读了内核源代码并找到了我的问题的答案。
save_stack calls
是由Kernel Address Sanitizer feature that was enabled in OpenVZ debug kernel by CONFIG_KASAN
option. When this options is enabled, on each kmem_cache_free syscall kernel calls __cache_free
static inline void __cache_free(struct kmem_cache *cachep, void *objp,
unsigned long caller)
{
/* Put the object into the quarantine, don't touch it for now. */
if (kasan_slab_free(cachep, objp))
return;
___cache_free(cachep, objp, caller);
}
禁用 CONFIG_KASAN
kasan_slab_free 将响应 false
(检查 include/linux/kasan.h
)。 OpenVZ 调试内核 was built 与 CONFIG_KASAN=y
,Amazon AMI 不是。