Да использование памяти, выделенной calloc()
, приведет к снижению производительности из-за исправлений Meltdown и Spectre.
На самом деле, calloc()
здесь не является особенным: malloc()
, new
и в целом вся выделенная память, вероятно, будет испытывать примерно одинаковое влияние на производительность. И calloc()
, и malloc()
в конечном итоге поддерживаются страницами, возвращаемыми ОС (хотя распределитель будет использовать их повторно после освобождения). Единственное реальное отличие состоит в том, что интеллектуальный распределитель, когда он идет по пути использования новых страниц из ОС (вместо повторного использования ранее free
d выделения) в случае calloc
, он может опускать обнуление, потому что страницы, предоставляемые ОС, гарантированно равны нулю. Кроме того, поведение распределителя в основном такое же, а поведение обнуления на уровне ОС одинаково (обычно нет возможности запросить у ОС ненулевые страницы).
Таким образом, влияние на производительность применяется шире, чем вы думали, но влияние на производительность, вероятно, будет меньше, чем вы предполагаете, так как сбой страницы в любом случае уже выполняет большую работу, так что вы не говорите о порядке ухудшения или что-нибудь. См. Ответ Питера о причинах, по которым влияние на производительность может быть ограничено. Я написал этот ответ главным образом потому, что ответ на ваш главный вопрос по-прежнему да , поскольку есть некоторое влияние.
Чтобы оценить влияние на тяжелый рабочий процесс malloc
, я попытался выполнить некоторое тяжелое тестирование выделения и сбоя страницы в текущем ядре (4.13.0-39-generic
) с мерами по уменьшению Specter и Meltdown, а также в более раннем ядре до на эти меры.
Тестовый код очень прост:
#include <stdlib.h>
#include <stdio.h>
#define SIZE (40 * 1024 * 1024)
#define PG_SIZE 4096
int main() {
char *mem = malloc(SIZE);
for (volatile char *p = mem; p < mem + SIZE; p += PG_SIZE) {
*p = 'z';
}
printf("pages touched: %d\npoitner value : %p\n", SIZE / PG_SIZE, mem);
}
Результаты на более новом ядре составляли около 3700 циклов на страницу, а на более старом ядре без уменьшения около 3300 циклов. Общая регрессия (предположительно) из-за смягчения последствий составила около 14%. Обратите внимание, что это на аппаратном обеспечении Skylake (i7-6700HQ), где некоторые из смягчений Specter'а несколько дешевле, а ядро поддерживает PCID, что удешевляет смягчение KPTI Meltdown. Результаты могут быть хуже на другом оборудовании.
Как ни странно, результаты по новому ядру с отключенными при загрузке Spectre и Meltdown (при использовании spectre_v2=off nopti
) были намного хуже , чем по умолчанию для нового или старого ядра, примерно 5050 ошибка циклов на странице, что-то вроде 35% -ной регрессии по тому же ядру с митигациями , включенными . Таким образом, что-то идет не так, с точки зрения производительности, когда смягчение отключено.
Полные результаты
Вот полный вывод perf stat
для двух прогонов.
Старое ядро (4.10.0-42)
pages touched: 10240
poitner value : 0x7f7d2561e010
Performance counter stats for './pagefaults':
12.980048 task-clock (msec) # 0.976 CPUs utilized
0 context-switches # 0.000 K/sec
0 cpu-migrations # 0.000 K/sec
10,286 page-faults # 0.792 M/sec
33,662,397 cycles # 2.593 GHz
27,230,864 instructions # 0.81 insn per cycle
4,535,443 branches # 349.417 M/sec
11,760 branch-misses # 0.26% of all branches
0.013293417 seconds time elapsed
Новое ядро (4.13.0-39)
pages touched: 10240
poitner value : 0x7f306ad69010
Performance counter stats for './pagefaults':
14.789615 task-clock (msec) # 0.966 CPUs utilized
8 context-switches # 0.541 K/sec
0 cpu-migrations # 0.000 K/sec
10,288 page-faults # 0.696 M/sec
38,318,595 cycles # 2.591 GHz
28,796,523 instructions # 0.75 insn per cycle
4,693,944 branches # 317.381 M/sec
26,853 branch-misses # 0.57% of all branches
0.015312764 seconds time elapsed
Новое ядро (4.13.0.-39) spectre_v2 = off nopti
pages touched: 10240
poitner value : 0x7ff079ede010
Performance counter stats for './pagefaults':
16.690621 task-clock (msec) # 0.982 CPUs utilized
0 context-switches # 0.000 K/sec
0 cpu-migrations # 0.000 K/sec
10,286 page-faults # 0.616 M/sec
51,964,080 cycles # 3.113 GHz
28,602,441 instructions # 0.55 insn per cycle
4,699,608 branches # 281.572 M/sec
25,064 branch-misses # 0.53% of all branches
0.017001581 seconds time elapsed