代码之家  ›  专栏  ›  技术社区  ›  Rob Paisley

什么会导致软件在更好的硬件上运行得更慢?

  •  3
  • Rob Paisley  · 技术社区  · 6 年前

    我有一个运行在RHEL7.4上的JavaOSGi(ApacheFelix)应用程序,它以大约975包/秒(1038个八位字节的长度)读取多播UDP。然后,它将数据转换为XML,模拟穿越边界设备,并将其转换回UDP多播数据包。涉及到多个线程,它的编写方式是,如果模拟边界设备处理一个负载需要一段时间,它会缓冲它,并在下次通过时发送更大的负载。

    当通过这个集成测试场景查看数据包延迟时,两个不同的桌面级机器明显快于我们期望部署的相当高端的服务器。

    • 服务器延迟5秒。硬件:双Xeon E5-2667v4@3.2GHz,128G内存,16个物理核,21个逻辑核,RAID 1 SAS固态硬盘。
    • 桌面A<1秒。HW Xeon E5-1620v4@3.5Ghz,64G内存,4个物理核,8个逻辑核,500G固态硬盘
    • 桌面B<1秒。HW i7-3770@3.4Ghz,16G内存,4个物理核,8个逻辑核,1TB 7200RPM驱动器。

    为了完整起见,我只提到硬盘驱动器,因为这个应用程序不会写入磁盘。在纸面上,服务器的运行速度至少应该和两台台式机一样快。

    我已经消除的东西:

    • 网卡。我已经用物理网卡和虚拟设备进行了测试,以防网卡之间存在显著差异。
    • 逻辑核心数。为了排除变量,我尝试禁用16个和24个服务器逻辑核心。
    • Java版本。这三个版本都已经在OpenJDK和Oracle的Java中试用过,它们都有相同的版本(Java 1.8.0 )产生相同的结果。
    • Java标志是相同的,并且都与felix(install directory,configuration properties,and jar to execute)相关。
    • 塞莱努克斯。我尝试过三种模式(禁用、强制、允许)。我没想到这里会有什么不同,但我在这一点上有所把握。
    • 内核版本。我试过测试 3.10.0 , 4.13.0 ,和 4.15.0 结果相似。

    ark.intel.com processor comparison

    这里有两个示例图来说明这个问题。此测试通过4分10秒将260960个UDP数据包发送到多播地址A,并在通过应用程序处理后,将这些数据包发送到多播地址B。 tcpdump 记录两者的时间戳,然后减法产生延迟。所有三个应用程序(发件人、应用程序、, 命令 在同一台机器上)。

    首先是针对虚拟接口的服务器硬件 server

    i7针对虚拟接口的桌面硬件 i7-desktop

    注意Y轴的尺度差。服务器为0-4秒,i7桌面为0-1秒。出现难以读取的X轴是包号。

    下一次尝试

    我正在运行应用程序的本地集成验证。然后,我消除了几乎100%由应用程序开始的工作,并看到服务器硬件上的延迟不断增加。我试过了 -Xmx100G -Xms100G 基本上是为了防止垃圾回收器运行并看到以下结果(<1秒一致延迟)。

    Huge Memory

    这让我 Java 8's Available Garbage Collectors .

    服务器硬件上的默认垃圾收集器选择是New:parallelsecruke,Old:ParallelOld。这是没有XML转换的结果延迟图,尽可能简单的一个测试来复制问题。

    Default GC

    显式选择垃圾第一垃圾收集器 -XX:+UseG1GC 选定的新:G1New,旧:G1Old,其结果延迟图不太好:

    G1 GC

    显式选择并发标记扫描垃圾收集器 -XX:+UseConcMarkSweepGC 选定的New:ParNew,Old:concurrentmarkswipe及其生成的延迟图看起来非常出色:

    CMS GC

    看来问题解决了。一旦我把所有的组件都添加回原处,我仍然会有不可接受的延迟。我还在做测试,看能不能把问题隔离开来。

    Strace结果

    尝试 strace -c -o /path/to/file -f 生成了以下顶级系统调用

    首先是i7的桌面 strace 报表(前10项截断)

    % time     seconds  usecs/call     calls    errors syscall
    ------ ----------- ----------- --------- --------- ----------------
     93.71 1418.604132         959   1479659    134352 futex
      1.74   26.294223      730395        36           poll
      1.74   26.288786         314     83645         4 read
      1.41   21.373672          73    293618           epoll_pwait
      1.19   17.952475         120    149854         2 recvfrom
      0.10    1.448453           2    909731           getrusage
      0.06    0.896903           3    281407           sendto
      0.03    0.394695           2    198041           write
      0.01    0.182809          10     18246           mmap
      0.01    0.120735           6     20582           sched_yield
    

    现在是服务器的 斯特拉斯 报告:

    % time     seconds  usecs/call     calls    errors syscall
    ------ ----------- ----------- --------- --------- ----------------
     97.46 2119.311196        2642    802183    131276 futex
      1.28   27.734136     6933534         4           poll
      0.59   12.840448          49    263597           epoll_wait
      0.41    8.885742         113     78387         2 recvfrom
      0.07    1.575401           6    263671           sendto
      0.07    1.515999           6    262256           epoll_ctl
      0.04    0.902788          54     16800           sched_yield
      0.03    0.743231          10     75455           write
      0.02    0.490052           6     84509         7 read
      0.01    0.170152           4     42732           lseek
    

    我不清楚我该从中得出什么结论。在这两种情况下,桌面的速度都要快很多倍 futex 以及 poll 系统调用。我仍然不明白为什么应用程序在更快的硬件上更隐蔽。

    剖析

    我已经分析了两个硬件上的软件,显示了热点的相似位置,这似乎排除了这一点。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Rob Paisley    6 年前

    我确认我用的是 performance 带RedHat的CPU调控器: CPUfreq Coverners

    我看到了一个关于有问题的BIOS设置的VMWare ESXi报告 Virtual Machine Application runs slower than expected on EXSi

    这直接指向了我的答案。此Dell R630上的默认值为“每瓦性能(DAPC)”(DAPC:Dell活动电源控制器)。切换到“性能”完全解决了这个问题。这台机器在控制台上感觉很快,而且延迟比台式机能够达到的要低得多,这是我在考虑到CPU差异的情况下所期望的。

    在启动时更改Dell R630(以及可能的其他)上的BIOS的步骤:

    1. 进入系统设置
    2. 选择“系统BIOS”
    3. 选择“系统配置文件设置”
    4. 确保第一项设置为“性能”默认值为“每瓦特性能”
    5. 选择“后退”
    6. 选择“完成”
    7. 选择“是”保存系统重置时的更改
    8. 选择“确定”以成功保存设置

    这是生成的延迟图,它们使用相同的1秒刻度。

    服务器上的默认GC: DefaultGC

    服务器上的并发标记扫描GC: CMSGC

    服务器上的第一代GC: G1GC

    G1GC和CMSGC之间没有太大的区别,但两者的延迟明显好于默认值(这是预期的)。

    逻辑核心时钟速度图

    符号很难看到,但这两张图上有32个不同的点。总的来说,您可以快速判断哪一个是性能,哪一个是每瓦dapc的性能。

    每瓦性能(DAPC): PerformancePerWattDAPC

    性能 Performance

    一起策划的。红色子弹的性能,蓝色圆圈的每瓦性能 Together

    这是在300秒的数据流中捕获的,BIOS会相应地进行设置。以下是我如何获取数据,以防有人想知道:

    for i in `seq 300`; do
      paste /sys/devices/system/cpu/cpu[0-9]*/cpufreq/cpuinfo_cur_freq
      sleep 1
    done > performance.log