Я использую perf в режиме выборки для сбора статистики производительности программ, работающих на многоядерной платформе с платформы NXP S32 Linux 4.19.
Например, конфигурация
Core 0 - App0 , Core 1 - App1, Core 2 - App2
Без выборки, то есть на уровне программы, App0 занимает 6,9 секунды.
При выборке с 1 миллионом циклов App0 занимает 6,3 сек c
При выборке с циклом 2 миллиона App0 занимает 6,4 с c
При выборке с циклом 5 миллионов App0 занимает 6,5 с c
При выборке с циклом 100 миллионов App0 занимает 6,8 se c.
Как вы можете видеть с более высоким периодом выборки (100 миллионов), App0 занимает больше времени, чтобы завершить выполнение sh.
На самом деле я ожидал обратного, то есть выборки при 1 миллион циклов должен был привести к тому, что программе потребовалось бы больше времени для выполнения из-за большего количества сгенерированных выборок (непроизводительных издержек) по сравнению со 100 миллионами циклов?
Я не могу объяснить это поведение Как вы думаете, что вызывает это?
Любые выводы будут полезны.
PS - На Pi3B поведение такое, как и ожидалось, т.е. выборка с 1 миллионами циклов приводит к более длительному времени выполнения по сравнению с 100 миллионами циклы.
ОБНОВЛЕНИЕ: я не использую perf из командной строки, вместо этого выполняю системный вызов perf, используя perf event
со следующими флагами в struct perf_event_attr
.
struct perf_event_attr hw_event;
pid_t pid = proccess_id; // measure the current process/thread
int cpu = -1; // measure on any cpu
unsigned long flags = 0;
int fd_current;
memset(&hw_event, 0, sizeof(struct perf_event_attr));
hw_event.type = event_type;
hw_event.size = sizeof(struct perf_event_attr);
hw_event.config = event;
if(group_fd == -1)
{
hw_event.sample_period = 2000000;
hw_event.sample_type = PERF_SAMPLE_READ;
hw_event.precise_ip = 1;
}
hw_event.disabled = 1; // off by default. specifies whether the counter starts out disabled or enabled.
hw_event.exclude_kernel = 0; // excluding events that happen in the kernel-space
hw_event.exclude_hv = 1; // excluding events that happen in the hypervisor
hw_event.pinned = pinned; // specifies the counter to be on the CPU if at all possible. applies only to hardware counters and only to group leaders.
hw_event.exclude_user = 0; // excludes events that happen in user space
hw_event.exclude_callchain_kernel = 0; // Do not include kernel callchains.
hw_event.exclude_callchain_user = 0; // Do not include user callchains.
hw_event.read_format = PERF_FORMAT_GROUP; // Allows all counter values in an event group to be read with one read
fd_current = syscall(__NR_perf_event_open, &hw_event, pid, cpu, group_fd, flags);
if (fd_current == -1) {
printf("Error opening leader %llx\n", hw_event.config);
exit(EXIT_FAILURE);
}
return fd_current;