Каково поведение записи perf по умолчанию?

#linux #perf

Вопрос:

Мне ясно, что perf всегда записывается одно или несколько событий, и выборка может быть основана на счетчиках или на времени. Но когда переключатели -e и -F не заданы, каково поведение по умолчанию perf record ? Страница руководства для perf-record не говорит вам, что она делает в этом случае.

Ответ №1:

Событие по умолчанию cycles , как можно увидеть, выполнив perf script после perf record . Там вы также можете видеть, что поведение выборки по умолчанию зависит от времени, поскольку количество циклов не является постоянным. Частота по умолчанию составляет 4000 Гц, что можно увидеть в исходном коде и проверить, сравнив размер файла или количество образцов с записью, в которой -F 4000 было указано.

В вики perf говорится, что частота составляет 1000 Гц, но это уже не так для ядер новее 3.4.

Комментарии:

1. Иногда, когда в процессоре есть PEBS/IBS, cycles:pp по умолчанию может использоваться событие (или :ppp для регулирования заноса). Последняя страница руководства man7.org/linux/man-pages/man1/perf-record.1.html документирует это как » Если в записи perf не указано-e, на гибридной платформе он создает два цикла по умолчанию и добавляет их в список событий. Один предназначен для ядра, другой-для атома».. Модификатор P, описанный в man perf-list man7.org/linux/man-pages/man1/perf-list.1.html#EVENT_MODIFIERS «Модификатор p можно использовать для указания того, насколько точным должен быть адрес инструкции».

Ответ №2:

Выбор события по умолчанию perf record выполняется в инструменте perf пользовательского пространства, который обычно распространяется как часть ядра Linux. С make perf-src-tar-gz помощью dir из исходного кода ядра linux мы можем сделать tar gz для быстрой перестройки или загрузить такой tar из https://mirrors.edge.kernel.org/pub/linux/kernel/tools/perf. Существует также несколько онлайн-средств просмотра перекрестных ссылок «LXR» для исходного кода ядра Linux, которые можно использовать так же, как grep, для изучения внутренних компонентов perf.

Существует функция выбора списка событий по умолчанию (evlist) для записи perf: __perf_evlist__add_default из файла tools/perf/util/evlist.c:

 int __perf_evlist__add_default(struct evlist *evlist, bool precise)
{
    struct evsel *evsel = perf_evsel__new_cycles(precise);
    evlist__add(evlist, evsel);
    return 0;
}
 

Вызывается из реализации записи perf в случае нулевых событий, проанализированных из опций: инструменты/perf/встроенная запись.c: int cmd_record()

 rec->evlist->core.nr_entries == 0 amp;amp;
    __perf_evlist__add_default(rec->evlist, !record.opts.no_samples)
 

И perf_evsel__new_cycles запросит циклы аппаратных событий (PERF_TYPE_HARDWARE PERF_COUNT_HW_CPU_CYCLES) с дополнительной выборкой ядра и максимальной точностью (проверьте модификаторы в man perf-list, это выборка EIP, обходные пути с использованием PEBS или IBS):

 struct evsel *perf_evsel__new_cycles(bool precise)
{
    struct perf_event_attr attr = {
        .type   = PERF_TYPE_HARDWARE,
        .config = PERF_COUNT_HW_CPU_CYCLES,
        .exclude_kernel = !perf_event_can_profile_kernel(),
    };
    struct evsel *evsel;

    /*
     * Now let the usual logic to set up the perf_event_attr defaults
     * to kick in when we return and before perf_evsel__open() is called.
     */
    evsel = evsel__new(amp;attr);
    evsel->precise_max = true;

    /* use asprintf() because free(evsel) assumes name is allocated */
    if (asprintf(amp;evsel->name, "cycles%s%s%.*s",
             (attr.precise_ip || attr.exclude_kernel) ? ":" : "",
             attr.exclude_kernel ? "u" : "",
             attr.precise_ip ? attr.precise_ip   1 : 0, "ppp") < 0)
    return evsel;
}
 

В случае сбоя perf_event_open (нет доступа к выборке аппаратных циклов, например, в виртуализированной среде без виртуализированного PMU) происходит возврат к программной выборке тактовой частоты процессора в инструментах/perf/встроенная запись.c: int record__open() какие вызовы perf_evsel__fallback() инструментов/perf/util/evsel.c:

 bool perf_evsel__fallback(struct evsel *evsel, int err,
              char *msg, size_t msgsize)
{
    if ((err == ENOENT || err == ENXIO || err == ENODEV) amp;amp;
        evsel->core.attr.type   == PERF_TYPE_HARDWARE amp;amp;
        evsel->core.attr.config == PERF_COUNT_HW_CPU_CYCLES) {
        /*
         * If it's cycles then fall back to hrtimer based
         * cpu-clock-tick sw counter, which is always available even if
         * no PMU support.
         */
        scnprintf(msg, msgsize, "%s", "The cycles event is not supported, trying to fall back to cpu-clock-ticks");

        evsel->core.attr.type   = PERF_TYPE_SOFTWARE;
        evsel->core.attr.config = PERF_COUNT_SW_CPU_CLOCK;

        return true;
    } ...
}