google / benchmark

A microbenchmark support library
Apache License 2.0
8.69k stars 1.59k forks source link

[BUG] --benchmark_perf_counters only counts user events #1601

Open jty2 opened 1 year ago

jty2 commented 1 year ago

Describe the bug Perf counter events specified using --benchmark_perf_counters only count user events. Event modifiers, like "event:k" to count kernel-only events, or without a modifier, like "event" to count user+kernel, only count user events, i.e., as if it's always "event:u".

System Which OS, compiler, and compiler version are you using:

To reproduce Steps to reproduce the behavior:

  1. Run a benchmark with --benchmark_perf_counters=INSTRUCTIONS:u,INSTRUCTIONS:k,INSTRUCTIONS
  2. See that the event counts are the same for all three, even though the event modifiers should have it count only user events, kernel events, or total events, respectively, and should most likely be different. At the very least, INSTRUCTIONS:u + INSTRUCTIONS:k should total to INSTRUCTIONS.

Expected behavior The :u modifier should count only user events. The :k modifier should count only kernel events. The event without a specified modifier should count both user and kernel events.

Additional context The reason is that PerfCounters::Create() overrides the perf_event_attr attr to exclude kernel and hv events and thus only counts user events.

https://github.com/google/benchmark/blob/v1.8.0/src/perf_counters.cc#L141

    attr.exclude_kernel = true;
    attr.exclude_user = false;
    attr.exclude_hv = true;

If these three lines are commented out, event modifiers appear to work as expected.

However, giving just the event name without any modifiers still counts only user events because the default mode is user mode only.

https://github.com/google/benchmark/blob/v1.8.0/src/perf_counters.cc#L85 const int kCounterMode = PFM_PLM3; // user mode only

Nonetheless, if both user and kernel modifiers are given, i.e. "INSTRUCTIONS:k:u", then both will be counted.