Skip to content

Commit 9bde93a

Browse files
ahunter6acmel
authored andcommitted
perf script: Add dlfilter__filter_event_early()
filter_event_early() can be more than 30% faster than filter_event() because it is called before internal filtering. In other respects it is the same as filter_event(), except that it will be passed events that have yet to be filtered out. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Leo Yan <leo.yan@linaro.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: https://lore.kernel.org/r/20210627131818.810-3-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
1 parent 291961f commit 9bde93a

5 files changed

Lines changed: 59 additions & 16 deletions

File tree

tools/perf/Documentation/perf-dlfilter.txt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,17 @@ const struct perf_dlfilter_fns perf_dlfilter_fns;
3636
int start(void **data, void *ctx);
3737
int stop(void *data, void *ctx);
3838
int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx);
39+
int filter_event_early(void *data, const struct perf_dlfilter_sample *sample, void *ctx);
3940
----
4041

4142
If implemented, 'start' will be called at the beginning, before any
42-
calls to 'filter_event' . Return 0 to indicate success,
43+
calls to 'filter_event' or 'filter_event_early'. Return 0 to indicate success,
4344
or return a negative error code. '*data' can be assigned for use by other
4445
functions. 'ctx' is needed for calls to perf_dlfilter_fns, but most
4546
perf_dlfilter_fns are not valid when called from 'start'.
4647

4748
If implemented, 'stop' will be called at the end, after any calls to
48-
'filter_event'. Return 0 to indicate success, or
49+
'filter_event' or 'filter_event_early'. Return 0 to indicate success, or
4950
return a negative error code. 'data' is set by 'start'. 'ctx' is needed
5051
for calls to perf_dlfilter_fns, but most perf_dlfilter_fns are not valid
5152
when called from 'stop'.
@@ -55,10 +56,13 @@ Return 0 to keep the sample event, 1 to filter it out, or return a negative
5556
error code. 'data' is set by 'start'. 'ctx' is needed for calls to
5657
'perf_dlfilter_fns'.
5758

59+
'filter_event_early' is the same as 'filter_event' except it is called before
60+
internal filtering.
61+
5862
The perf_dlfilter_sample structure
5963
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6064

61-
'filter_event' is passed a perf_dlfilter_sample
65+
'filter_event' and 'filter_event_early' are passed a perf_dlfilter_sample
6266
structure, which contains the following fields:
6367
[source,c]
6468
----
@@ -105,7 +109,8 @@ The perf_dlfilter_fns structure
105109
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
106110

107111
The 'perf_dlfilter_fns' structure is populated with function pointers when the
108-
file is loaded. The functions can be called by 'filter_event'.
112+
file is loaded. The functions can be called by 'filter_event' or
113+
'filter_event_early'.
109114

110115
[source,c]
111116
----

tools/perf/builtin-script.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2179,9 +2179,20 @@ static int process_sample_event(struct perf_tool *tool,
21792179
struct addr_location addr_al;
21802180
int ret = 0;
21812181

2182+
/* Set thread to NULL to indicate addr_al and al are not initialized */
2183+
addr_al.thread = NULL;
2184+
al.thread = NULL;
2185+
2186+
ret = dlfilter__filter_event_early(dlfilter, event, sample, evsel, machine, &al, &addr_al);
2187+
if (ret) {
2188+
if (ret > 0)
2189+
ret = 0;
2190+
goto out_put;
2191+
}
2192+
21822193
if (perf_time__ranges_skip_sample(scr->ptime_range, scr->range_num,
21832194
sample->time)) {
2184-
return 0;
2195+
goto out_put;
21852196
}
21862197

21872198
if (debug_mode) {
@@ -2192,24 +2203,22 @@ static int process_sample_event(struct perf_tool *tool,
21922203
nr_unordered++;
21932204
}
21942205
last_timestamp = sample->time;
2195-
return 0;
2206+
goto out_put;
21962207
}
21972208

21982209
if (filter_cpu(sample))
2199-
return 0;
2210+
goto out_put;
22002211

22012212
if (machine__resolve(machine, &al, sample) < 0) {
22022213
pr_err("problem processing %d event, skipping it.\n",
22032214
event->header.type);
2204-
return -1;
2215+
ret = -1;
2216+
goto out_put;
22052217
}
22062218

22072219
if (al.filtered)
22082220
goto out_put;
22092221

2210-
/* Set thread to NULL to indicate addr_al is not initialized */
2211-
addr_al.thread = NULL;
2212-
22132222
if (!show_event(sample, evsel, al.thread, &al, &addr_al))
22142223
goto out_put;
22152224

@@ -2238,7 +2247,8 @@ static int process_sample_event(struct perf_tool *tool,
22382247
}
22392248

22402249
out_put:
2241-
addr_location__put(&al);
2250+
if (al.thread)
2251+
addr_location__put(&al);
22422252
return ret;
22432253
}
22442254

tools/perf/util/dlfilter.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ static int dlfilter__open(struct dlfilter *d)
175175
}
176176
d->start = dlsym(d->handle, "start");
177177
d->filter_event = dlsym(d->handle, "filter_event");
178+
d->filter_event_early = dlsym(d->handle, "filter_event_early");
178179
d->stop = dlsym(d->handle, "stop");
179180
d->fns = dlsym(d->handle, "perf_dlfilter_fns");
180181
if (d->fns)
@@ -251,7 +252,8 @@ int dlfilter__do_filter_event(struct dlfilter *d,
251252
struct evsel *evsel,
252253
struct machine *machine,
253254
struct addr_location *al,
254-
struct addr_location *addr_al)
255+
struct addr_location *addr_al,
256+
bool early)
255257
{
256258
struct perf_dlfilter_sample d_sample;
257259
struct perf_dlfilter_al d_ip_al;
@@ -322,7 +324,10 @@ int dlfilter__do_filter_event(struct dlfilter *d,
322324

323325
d->ctx_valid = true;
324326

325-
ret = d->filter_event(d->data, &d_sample, d);
327+
if (early)
328+
ret = d->filter_event_early(d->data, &d_sample, d);
329+
else
330+
ret = d->filter_event(d->data, &d_sample, d);
326331

327332
d->ctx_valid = false;
328333

tools/perf/util/dlfilter.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ struct dlfilter {
4040
int (*filter_event)(void *data,
4141
const struct perf_dlfilter_sample *sample,
4242
void *ctx);
43+
int (*filter_event_early)(void *data,
44+
const struct perf_dlfilter_sample *sample,
45+
void *ctx);
4346

4447
struct perf_dlfilter_fns *fns;
4548
};
@@ -54,7 +57,8 @@ int dlfilter__do_filter_event(struct dlfilter *d,
5457
struct evsel *evsel,
5558
struct machine *machine,
5659
struct addr_location *al,
57-
struct addr_location *addr_al);
60+
struct addr_location *addr_al,
61+
bool early);
5862

5963
void dlfilter__cleanup(struct dlfilter *d);
6064

@@ -68,7 +72,20 @@ static inline int dlfilter__filter_event(struct dlfilter *d,
6872
{
6973
if (!d || !d->filter_event)
7074
return 0;
71-
return dlfilter__do_filter_event(d, event, sample, evsel, machine, al, addr_al);
75+
return dlfilter__do_filter_event(d, event, sample, evsel, machine, al, addr_al, false);
76+
}
77+
78+
static inline int dlfilter__filter_event_early(struct dlfilter *d,
79+
union perf_event *event,
80+
struct perf_sample *sample,
81+
struct evsel *evsel,
82+
struct machine *machine,
83+
struct addr_location *al,
84+
struct addr_location *addr_al)
85+
{
86+
if (!d || !d->filter_event_early)
87+
return 0;
88+
return dlfilter__do_filter_event(d, event, sample, evsel, machine, al, addr_al, true);
7289
}
7390

7491
#endif

tools/perf/util/perf_dlfilter.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,10 @@ int stop(void *data, void *ctx);
120120
*/
121121
int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx);
122122

123+
/*
124+
* The same as 'filter_event' except it is called before internal
125+
* filtering.
126+
*/
127+
int filter_event_early(void *data, const struct perf_dlfilter_sample *sample, void *ctx);
128+
123129
#endif

0 commit comments

Comments
 (0)