Performance 如何消除CPU内核数量增加带来的开销

Performance 如何消除CPU内核数量增加带来的开销,performance,networking,linux-kernel,multicore,Performance,Networking,Linux Kernel,Multicore,我们遇到的情况是,一台具有8个核心的服务器在6分钟内初始化服务,而另一台具有32个cpu核心的服务器则需要35分钟来初始化服务。在正确地分析它之后,我们发现这是由于两个内核API(get_计数器和snmp_fold_字段)造成的它尝试从每个现有内核收集数据,随着cpu内核数量的增加,执行时间比预期的要长。为了减少初始化时间,我们考虑禁用额外的内核,然后启用所有cpu内核。但在这种方法中,一旦启用所有内核,也会在新启用的内核,因为这是SMP内核 有人能建议我们如何有效地减少CPU内核增加带来的开销

我们遇到的情况是,一台具有8个核心的服务器在6分钟内初始化服务,而另一台具有32个cpu核心的服务器则需要35分钟来初始化服务。在正确地分析它之后,我们发现这是由于两个内核API(get_计数器和snmp_fold_字段)造成的它尝试从每个现有内核收集数据,随着cpu内核数量的增加,执行时间比预期的要长。为了减少初始化时间,我们考虑禁用额外的内核,然后启用所有cpu内核。但在这种方法中,一旦启用所有内核,也会在新启用的内核,因为这是SMP内核

有人能建议我们如何有效地减少CPU内核增加带来的开销吗


我宁愿解释这个用户定义的系统服务的初始化功能,而不是代码。在初始化过程中,这个服务在配置的IP上探测虚拟接口。为避免每个配置的IP出现重叠的IP情况,它会创建一个内部IP,所有通信都在内部IP上的接口上完成。当数据包到达目的地为配置的IP的系统时,会在系统上应用Mangling/NATting/Routing table规则对其进行管理。 配置Ip的接口也是垂直的,以避免Ip转发。我们的问题是,当我们在8核机器上扩展配置为1024个Ip的系统时,需要8分钟,在32核机器上则需要35分钟


在使用系统评测完成的进一步调试中,我们看到ARPtables/IPtables的内核模块在“get_counters()”中消耗的时间最多,而IP的内核模块在snmp_fold_field()中消耗的时间最多。如果我简单地禁用ARPtables,混乱规则的时间将从35分钟减少到18分钟。我可以共享使用profiler收集的内核模块调用堆栈。

在使用多核的应用程序中,一个常见的瓶颈是对共享资源的无控制/优化访问。最大的性能杀手是总线锁(关键部分),其次是对RAM的访问、对三级缓存的访问和对二级缓存的访问。只要核心在其自己的L1(代码和数据)缓存中运行,唯一的瓶颈将是由于编写糟糕的代码和组织不良的数据。当两个内核需要离开它们的一级缓存时,它们在访问它们的(共享的)二级缓存时可能会发生冲突。谁先去?数据是否存在,或者我们必须向下移动到L3或RAM才能访问它?对于查找数据所需的每一级,您将面临3-4倍的时间惩罚

关于您的应用程序,它似乎工作得相当好,因为在访问共享资源时,八个内核只能在一定程度上发生冲突。有了32个内核,问题会变得比原来大四倍多,因为要解决谁先访问的问题,资源的压力将是原来的四倍,内核的数量将是原来的四倍。这就像一个门口:只要有几个人不时地从门口跑进来跑出去,就没有问题。接近门口的人可能会停下来让另一个人通过。突然间,你会遇到很多人跑进跑出的情况,你不仅会遇到交通堵塞,还会遇到交通堵塞

我给您的建议是,尝试限制应用程序在任何时候可以使用的线程数(这将转化为内核数)。八个内核上六分钟的启动时间可以作为基准。您可能会发现,它在四个内核上的执行速度比在八个内核上快,更不用说三十二个了


如果是这种情况,并且您仍然坚持在32个内核上比现在运行得更快,那么您将看到大量的工作,包括提高SNMP服务器代码的效率和组织数据以减轻共享资源的负载。不适合胆小的人。您可能会重新编写整个应用程序。

编写一个显示该行为的小程序。我们的应用程序使用的线程数非常少,但我们使用第三方应用程序,如“ip”、“iptables”和“arptables”,它们在内部调用两个API get_sockopt()和recvmsg()。这些API在内核中花费的时间更长。它们在内核中对应的API是get_sockopt()和snmp_fold_field()[我前面提到过它们]。您需要确定它们在多大程度上导致了不利的开销特性。尝试减少IP的数量,看看是否有可能为四个内核找到一个最佳点,为三十二个内核找到另一个最佳点。