perf intel-pt: Fix instructions sampling rate
authorAdrian Hunter <adrian.hunter@intel.com>
Fri, 10 May 2019 12:41:41 +0000 (15:41 +0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 16 May 2019 17:17:23 +0000 (14:17 -0300)
The timestamp used to determine if an instruction sample is made, is an
estimate based on the number of instructions since the last known
timestamp. A consequence is that it might go backwards, which results in
extra samples. Change it so that a sample is only made when the
timestamp goes forwards.

Note this does not affect a sampling period of 0 or sampling periods
specified as a count of instructions.

Example:

 Before:

 $ perf script --itrace=i10us
 ls 13812 [003] 2167315.222583:       3270 instructions:u:      7fac71e2e494 __GI___tunables_init+0xf4 (/lib/x86_64-linux-gnu/ld-2.28.so)
 ls 13812 [003] 2167315.222667:      30902 instructions:u:      7fac71e2da0f _dl_cache_libcmp+0x2f (/lib/x86_64-linux-gnu/ld-2.28.so)
 ls 13812 [003] 2167315.222667:         10 instructions:u:      7fac71e2d9ff _dl_cache_libcmp+0x1f (/lib/x86_64-linux-gnu/ld-2.28.so)
 ls 13812 [003] 2167315.222667:          8 instructions:u:      7fac71e2d9ea _dl_cache_libcmp+0xa (/lib/x86_64-linux-gnu/ld-2.28.so)
 ls 13812 [003] 2167315.222667:         14 instructions:u:      7fac71e2d9ea _dl_cache_libcmp+0xa (/lib/x86_64-linux-gnu/ld-2.28.so)
 ls 13812 [003] 2167315.222667:          6 instructions:u:      7fac71e2d9ff _dl_cache_libcmp+0x1f (/lib/x86_64-linux-gnu/ld-2.28.so)
 ls 13812 [003] 2167315.222667:         14 instructions:u:      7fac71e2d9ff _dl_cache_libcmp+0x1f (/lib/x86_64-linux-gnu/ld-2.28.so)
 ls 13812 [003] 2167315.222667:          4 instructions:u:      7fac71e2dab2 _dl_cache_libcmp+0xd2 (/lib/x86_64-linux-gnu/ld-2.28.so)
 ls 13812 [003] 2167315.222728:      16423 instructions:u:      7fac71e2477a _dl_map_object_deps+0x1ba (/lib/x86_64-linux-gnu/ld-2.28.so)
 ls 13812 [003] 2167315.222734:      12731 instructions:u:      7fac71e27938 _dl_name_match_p+0x68 (/lib/x86_64-linux-gnu/ld-2.28.so)
 ...

 After:
 $ perf script --itrace=i10us
 ls 13812 [003] 2167315.222583:       3270 instructions:u:      7fac71e2e494 __GI___tunables_init+0xf4 (/lib/x86_64-linux-gnu/ld-2.28.so)
 ls 13812 [003] 2167315.222667:      30902 instructions:u:      7fac71e2da0f _dl_cache_libcmp+0x2f (/lib/x86_64-linux-gnu/ld-2.28.so)
 ls 13812 [003] 2167315.222728:      16479 instructions:u:      7fac71e2477a _dl_map_object_deps+0x1ba (/lib/x86_64-linux-gnu/ld-2.28.so)
 ...

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: stable@vger.kernel.org
Fixes: f4aa081949e7b ("perf tools: Add Intel PT decoder")
Link: http://lkml.kernel.org/r/20190510124143.27054-2-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c

index 872fab163585ac9dcf6b42ab7d95e8cae651714b..26dbf11e071a228bc7c1202f5891a07a28e1db7e 100644 (file)
@@ -888,16 +888,20 @@ static uint64_t intel_pt_next_period(struct intel_pt_decoder *decoder)
        timestamp = decoder->timestamp + decoder->timestamp_insn_cnt;
        masked_timestamp = timestamp & decoder->period_mask;
        if (decoder->continuous_period) {
-               if (masked_timestamp != decoder->last_masked_timestamp)
+               if (masked_timestamp > decoder->last_masked_timestamp)
                        return 1;
        } else {
                timestamp += 1;
                masked_timestamp = timestamp & decoder->period_mask;
-               if (masked_timestamp != decoder->last_masked_timestamp) {
+               if (masked_timestamp > decoder->last_masked_timestamp) {
                        decoder->last_masked_timestamp = masked_timestamp;
                        decoder->continuous_period = true;
                }
        }
+
+       if (masked_timestamp < decoder->last_masked_timestamp)
+               return decoder->period_ticks;
+
        return decoder->period_ticks - (timestamp - masked_timestamp);
 }
 
@@ -926,7 +930,10 @@ static void intel_pt_sample_insn(struct intel_pt_decoder *decoder)
        case INTEL_PT_PERIOD_TICKS:
                timestamp = decoder->timestamp + decoder->timestamp_insn_cnt;
                masked_timestamp = timestamp & decoder->period_mask;
-               decoder->last_masked_timestamp = masked_timestamp;
+               if (masked_timestamp > decoder->last_masked_timestamp)
+                       decoder->last_masked_timestamp = masked_timestamp;
+               else
+                       decoder->last_masked_timestamp += decoder->period_ticks;
                break;
        case INTEL_PT_PERIOD_NONE:
        case INTEL_PT_PERIOD_MTC: