Performance 分析不同内核版本性能下降的原因

Performance 分析不同内核版本性能下降的原因,performance,linux-kernel,perf,radiance,Performance,Linux Kernel,Perf,Radiance,在x86_64系统上,我遇到了从Linux内核3.11到3.12的奇怪性能回归。 在Fedora20上运行,3.12的速度明显较慢。没有其他改变-相同的二进制文件,相同的glibc-我只是启动了一个不同的内核版本,性能也发生了变化。 定时程序rpict是100%绑定CPU的用户级代码 在我将其报告为bug之前,我想找出这种行为的原因。我对Linux内核了解不多,从3.11到3.12的更改日志也没有给我任何线索 我在Intel Haswell(i7-4771)和AMD Richland(A8-66

在x86_64系统上,我遇到了从Linux内核3.11到3.12的奇怪性能回归。 在Fedora20上运行,3.12的速度明显较慢。没有其他改变-相同的二进制文件,相同的glibc-我只是启动了一个不同的内核版本,性能也发生了变化。 定时程序rpict是100%绑定CPU的用户级代码

在我将其报告为bug之前,我想找出这种行为的原因。我对Linux内核了解不多,从3.11到3.12的更改日志也没有给我任何线索

我在Intel Haswell(i7-4771)和AMD Richland(A8-6600K)两个系统上观察到了这一点。 在Haswell系统上,用户时间从895秒(3.11秒)增加到962秒(3.12秒)。从1764年到1844年,在里奇兰。这些时间可以在几秒钟内重复

我对perf做了一些分析,发现IPC的下降与经济放缓的比例相同。在Haswell系统上,这似乎是由于更多的分支缺失造成的,但是为什么预测率应该下降呢?Radiance确实使用了随机数生成器-更好的随机性会导致遗漏分支吗?但除了OMAP4支持外,RNG在3.12中似乎不需要更改

在AMD系统上,perf只是指向更多的空闲后端周期,但原因尚不清楚

哈斯韦尔系统:

3.11.10  895s user, 3.74% branch-misses, 1.65 insns per cycle
3.12.6   962s user, 4.22% branch-misses, 1.52 insns per cycle
里奇兰系统:

3.11.10  1764s user, 8.23% branch-misses, 0.75 insns per cycle
3.12.6   1844s user, 8.26% branch-misses, 0.72 insns per cycle
我还查看了两个内核的dmesg输出的差异,但没有看到任何可能导致CPU受限程序如此缓慢的原因

我尝试将cpufreq调控器从默认的ondemand切换到PePerformance,但没有任何效果

可执行文件是使用GCC4.7.3编译的,但没有使用AVX指令。libm似乎仍然使用一些AVX(例如,
\uuIEEE754\uPOW\uFMA4
),但这些函数仅占总执行时间的0.3%

其他信息:

  • 关于哈斯韦尔系统
  • -3.11仅映射一个堆区域;3.12地段
  • 来自A8-6600K系统
  • dTLB统计数据看起来非常不同
  • 来自A8-6600K系统

有什么想法吗(除了将内核更改一分为二)?

这个更改可能是一个候选方案。我说得很随便,因为我没有足够的资源来证实。值得注意的是,这是3.11.10和3.12.6之间对调度器的唯一重大更改


无论如何,我非常有兴趣看到你的发现的最终结果,所以请随时通知我们

让我们检查您的
perf stat
输出:

内核3.11.10

    1805057.522096 task-clock                #    0.999 CPUs utilized          
           183,822 context-switches          #    0.102 K/sec                  
               109 cpu-migrations            #    0.000 K/sec                  
            40,451 page-faults               #    0.022 K/sec                  
 7,523,630,814,458 cycles                    #    4.168 GHz                     [83.31%]
   628,027,409,355 stalled-cycles-frontend   #    8.35% frontend cycles idle    [83.34%]
 2,688,621,128,444 stalled-cycles-backend    #   35.74% backend  cycles idle    [33.35%]
 5,607,337,995,118 instructions              #    0.75  insns per cycle        
                                             #    0.48  stalled cycles per insn [50.01%]
   825,679,208,404 branches                  #  457.425 M/sec                   [66.67%]
    67,984,693,354 branch-misses             #    8.23% of all branches         [83.33%]

    1806.804220050 seconds time elapsed
内核3.12.6

    1875709.455321 task-clock                #    0.999 CPUs utilized          
           192,425 context-switches          #    0.103 K/sec                  
               133 cpu-migrations            #    0.000 K/sec                  
            40,356 page-faults               #    0.022 K/sec                  
 7,822,017,368,073 cycles                    #    4.170 GHz                     [83.31%]
   634,535,174,769 stalled-cycles-frontend   #    8.11% frontend cycles idle    [83.34%]
 2,949,638,742,734 stalled-cycles-backend    #   37.71% backend  cycles idle    [33.35%]
 5,607,926,276,713 instructions              #    0.72  insns per cycle        
                                             #    0.53  stalled cycles per insn [50.01%]
   825,760,510,232 branches                  #  440.239 M/sec                   [66.67%]
    68,205,868,246 branch-misses             #    8.26% of all branches         [83.33%]

    1877.263511002 seconds time elapsed
在“周期”字段中,3.12.6中有近300个Gcycles;只有6,5辆Gcycles在前端暂停,261辆Gcycles在后端暂停。您只有0,2 G额外的分支未命中(每个分支未命中大约花费20个周期-每个optim.manual第597页;所以4G个周期),因此我认为您的性能问题与内存子系统问题有关(更现实的后端事件,可能会受到内核的影响)。Pagefaults差异和迁移计数很低,我认为它们不会直接降低测试速度(但迁移可能会使程序变得更糟)

您应该深入到
perf
计数器中,以找到问题的确切类型(如果您的测试运行时间较短,则会更容易)。英特尔的手册将帮助您。查看第587页(B.3.2)了解整体事件层次结构(FE和BE暂停也在此处),查看B.3.2.1-B.3.2.3了解后端暂停的信息以及如何开始挖掘(检查缓存事件等)及以下内容

内核如何影响内存子系统?它可以设置不同的虚拟到物理映射(这与您的情况不同),也可以将进程从数据移动到更远的位置。您没有NUMA机器,但Haswell不是确切的UMA-有一个环形总线,一些内核更接近内存控制器或共享LLC(最后一级缓存)的某些部分。您可以使用
taskset
实用程序测试您的程序,将其绑定到某个核心-内核不会将其移动到其他核心

更新:在检查A8的新性能统计数据后,我们发现3.12.6中有更多的DLTB未命中。随着/proc/pid/maps的变化(大量的短
[heap]
节而不是单个
[heap]
,仍然没有确切的原因),我认为透明的hugepage可能会有所不同(THP;对于2M的hugepages,相同内存量所需的TLB条目更少,TLB未命中也更少),例如,在3.12中,由于堆段较短,因此无法应用它

您可以检查
/proc/PID/smap
中的
anonhuggepages
/proc/vmstat
中的thp*值,以查看thp结果。值记录在kernel.org/doc/Documentation/vm/transhage.txt中

@你找到了原因!在echo never>/sys/kernel/mm/transparent\u hugepage/enabled之后,3.11.10需要的时间与3.12.6一样长

好消息

关于如何禁用随机化,以及在何处将其报告为错误(7%的性能回归非常严重)的其他信息将不胜感激

我错了,这种多堆分段效应不是brk随机化(它只改变堆的开头)。这是
dobrk
中的VMA合并失败;不知道为什么,但是在3.11.10-3.12.6之间的
mm
中可以看到VM_SOFTDIRTY的一些变化

UPDATE2:未合并VMA的可能原因:

请在3.11中点击

请在3.12中点击

3.12刚刚添加到
do_brk

2663        vma->vm_flags |= VM_SOFTDIRTY;
2664        return addr;
还有一点我们有

2635        /* Can we just expand an old private anonymous mapping? */
2636        vma = vma_merge(mm, prev, addr, addr + len, flags,
2637                                        NULL, NULL, pgoff, NULL);
vma_merge
内部,有对vm_标志的测试

3.11

3.12

vma_合并-->可以在-->可合并之前\u vma_合并\u

 898        if (vma->vm_flags ^ vm_flags)
 899                return 0;

但在检查时,新vma未标记为VM_SOFTDIRTY,而旧vma已标记。

您可以尝试使用一些不同的基准测试,看看它们与辐射度基准测试的比较情况。了解工作负载中运行较慢的内容可能会有所帮助。@sup
 898        if (vma->vm_flags ^ vm_flags)
 899                return 0;