nnnmmm
nnnmmm

Reputation: 8804

What is the default behavior of perf record?

It's clear to me that perf always records one or more events, and the sampling can be counter-based or time-based. But when the -e and -F switches are not given, what is the default behavior of perf record? The manpage for perf-record doesn't tell you what it does in this case.

Upvotes: 6

Views: 2306

Answers (2)

osgx
osgx

Reputation: 94455

Default event selection in perf record is done in user-space perf tool which is usually distributed as part of linux kernel. With make perf-src-tar-gz from linux kernel source dir we can make tar gz for quick rebuild or download such tar from https://mirrors.edge.kernel.org/pub/linux/kernel/tools/perf. There are also several online "LXR" cross-reference viewers for linux kernel source which can be used just like grep to learn about perf internals.

There is the function to select default event list (evlist) for perf record: __perf_evlist__add_default of tools/perf/util/evlist.c file:

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

Called from perf record implementation in case of zero events parsed from options: tools/perf/builtin-record.c: int cmd_record()

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

And perf_evsel__new_cycles will ask for hardware event cycles (PERF_TYPE_HARDWARE + PERF_COUNT_HW_CPU_CYCLES) with optional kernel sampling, and max precise (check modifiers in man perf-list, it is EIP sampling skid workarounds using PEBS or 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(&attr);
    evsel->precise_max = true;

    /* use asprintf() because free(evsel) assumes name is allocated */
    if (asprintf(&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;
}

In case of failed perf_event_open (no access to hardware cycles sampling, for example in virtualized environment without virtualized PMU) there is failback to software cpu-clock sampling in tools/perf/builtin-record.c: int record__open() which calls perf_evsel__fallback() of tools/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) &&
        evsel->core.attr.type   == PERF_TYPE_HARDWARE &&
        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;
    } ...
}

Upvotes: 2

nnnmmm
nnnmmm

Reputation: 8804

The default event is cycles, as can be seen by running perf script after perf record. There, you can also see that the default sampling behavior is time-based, since the number of cycles is not constant. The default frequency is 4000 Hz, which can be seen in the source code and checked by comparing the file size or number of samples to a recording where -F 4000 was specified.

The perf wiki says that the rate is 1000 Hz, but this is not true anymore for kernels newer than 3.4.

Upvotes: 8

Related Questions