снижение производительности при включенном PTI в Linux-4.4.0

Я выполняю тест Java на Ubuntu 16.04 и обнаружил разницу в производительности при включении и выключении PTI.
Моя хост-система использует ЦП Ivybridge (2 ядра, 4 HT) 1,6 ГГц с памятью 16 ГБ.

Я попытался использовать perf, чтобы проанализировать, откуда берется разница, следующим образом.

Если pti=off в grub.cfg,

# perf  stat -e bus-cycles,cache-misses,cache-references,L1-dcache-load-misses,dTLB-load-misses,L1-dcache-prefetch-misses,LLC-prefetches ./test.sh 

 Performance counter stats for './test.sh':

       774,986,827      bus-cycles                                                    (59.13%)
        24,044,906      cache-misses              #   12.803 % of all cache refs      (58.17%)
       187,799,652      cache-references                                              (57.51%)
       207,345,039      L1-dcache-load-misses                                         (57.65%)
        13,081,612      dTLB-load-misses                                              (58.85%)
        22,678,453      L1-dcache-prefetch-misses                                     (59.62%)
        24,089,506      LLC-prefetches                                                (59.99%)

       6.210151360 seconds time elapsed

и с pti=on (настройки по умолчанию в ядре Linux) я получил,

# perf stat -e bus-cycles,cache-misses,cache-references,L1-dcache-load-misses,dTLB-load-misses,L1-dcache-prefetch-misses,LLC-prefetches ./test.sh 

Статистика счетчика производительности для './test.sh':

 1,205,903,578      bus-cycles                                                    (57.92%)
    23,877,107      cache-misses              #   13.167 % of all cache refs      (57.31%)
   181,340,147      cache-references                                              (57.46%)
   206,177,901      L1-dcache-load-misses                                         (58.42%)
    63,285,591      dTLB-load-misses                                              (59.06%)
    24,012,988      L1-dcache-prefetch-misses                                     (58.65%)
    24,928,410      LLC-prefetches                                                (58.23%)

  10.344839116 seconds time elapsed  

test.sh — это программа, которую нужно профилировать, из приведенного выше вывода perf, test.sh занял больше времени с pti=on, чем с pti=off, но вывод события НЕ ЯСНО, в чем разница.
Есть ли какие-либо другие perf событие может помочь в этом случае?

Обновлено с дополнительными событиями производительности.
PTI=off

# perf stat --repeat 5 -e cache-references,cache-misses,cpu-cycles,ref-cycles,faults,L1-dcache-loads,L1-dcache-load-misses,L1-icache-load-misses,branches,branch-misses,node-loads,node-load-misses,instructions,cs java mytest

 Performance counter stats for 'java mytest' (5 runs):

         8,711,306      cache-references                                              ( +-  4.13% )  (48.49%)
         1,290,234      cache-misses              #   14.811 % of all cache refs      ( +-  4.04% )  (49.44%)
       709,587,381      cpu-cycles                                                    ( +-  1.44% )  (48.91%)
       671,299,480      ref-cycles                                                    ( +-  1.95% )  (58.09%)
             5,918      faults                                                        ( +-  0.12% )
       185,928,475      L1-dcache-loads                                               ( +-  4.29% )  (35.90%)
         9,249,983      L1-dcache-load-misses     #    4.98% of all L1-dcache hits    ( +-  5.91% )  (27.84%)
         4,718,632      L1-icache-load-misses                                         ( +-  5.47% )  (20.83%)
       106,021,866      branches                                                      ( +-  1.98% )  (31.56%)
         4,487,091      branch-misses             #    4.23% of all branches          ( +-  5.35% )  (40.34%)
           450,170      node-loads                                                    ( +-  9.18% )  (38.32%)
                 0      node-load-misses                                              (40.62%)
       509,344,631      instructions              #    0.72  insns per cycle          ( +-  5.59% )  (49.64%)
               458      cs                                                            ( +-  2.05% )

       0.216794242 seconds time elapsed                                          ( +-  3.44% )   

PTI=ВКЛ.

# perf stat --repeat 5 -e cache-references,cache-misses,cpu-cycles,ref-cycles,faults,L1-dcache-loads,L1-dcache-load-misses,L1-icache-load-misses,branches,branch-misses,node-loads,node-load-misses,instructions,cs java mytest

 Performance counter stats for 'java mytest' (5 runs):

        10,109,469      cache-references                                              ( +-  4.10% )  (44.67%)
         1,360,012      cache-misses              #   13.453 % of all cache refs      ( +-  2.16% )  (45.28%)
     1,199,960,141      cpu-cycles                                                    ( +-  2.44% )  (46.13%)
     1,086,243,141      ref-cycles                                                    ( +-  1.28% )  (54.64%)
             5,923      faults                                                        ( +-  0.24% )
       163,902,394      L1-dcache-loads                                               ( +-  3.46% )  (41.91%)
         8,588,505      L1-dcache-load-misses     #    5.24% of all L1-dcache hits    ( +-  5.59% )  (27.82%)
         5,576,811      L1-icache-load-misses                                         ( +-  3.87% )  (18.41%)
       117,508,300      branches                                                      ( +-  3.98% )  (27.34%)
         4,878,640      branch-misses             #    4.15% of all branches          ( +-  2.28% )  (35.55%)
           585,464      node-loads                                                    ( +-  9.05% )  (34.55%)
                 0      node-load-misses                                              (36.68%)
       614,773,322      instructions              #    0.51  insns per cycle          ( +-  4.11% )  (46.10%)
               476      cs                                                            ( +-  2.75% )

       0.375871969 seconds time elapsed                                          ( +-  0.81% )

person wangt13    schedule 13.06.2018    source источник
comment
Вы действительно должны использовать ocperf.py (github.com/andikleen/pmu-tools) и использовать осмысленное HW -специфические имена для событий HW. Я думаю, что cache-references на самом деле является загрузкой L3 или чем-то в семействе Intel SnB. См. также другую информацию/ссылки на производительность x86 asm в вики тега x86 stackoverflow.com/tags/x86/info.   -  person Peter Cordes    schedule 13.06.2018


Ответы (1)


Понятия не имею, какое событие на самом деле измеряют «циклы шины». тактовые циклы ядра обычно более актуальны.

Но в любом случае, PTI=on делает каждый системный вызов (и другой вход в ядро) более дорогим, потому что он должен модифицировать управляющий регистр x86 CR3 (устанавливая новый указатель верхнего уровня таблицы страниц). Это буквально то, как он изолирует пространство пользователя от доступа к таблицам страниц ядра.

Обратите внимание на значительное увеличение dTLB-load-misses. Благодаря поддержке идентификаторов контекста процесса (PCID) PTI может избежать полной очистки TLB каждый раз, когда он входит в ядро. Но я не знаю подробностей. (Без PCID замена таблиц страниц делает недействительным весь TLB.)

Вы можете использовать strace -c для определения времени системных вызовов.

С помощью perf record (с достаточными привилегиями) вы можете записывать примеры, включающие код ядра, чтобы вы могли видеть, какие инструкции в ядре на самом деле заняли много времени. (Переход к CR3 также требует времени, как и устранение последствий Spectre, которое отделено от смягчения последствий Meltdown (PTI). Но я думаю, что большая часть стоимости смягчения последствий Meltdown связана с промахами TLB с течением времени внутри ядра и снова после возврата в пользовательское пространство, а не из фактического обмена таблицами страниц.)

person Peter Cordes    schedule 13.06.2018