Skip to content

Commit b339da4

Browse files
author
Ingo Molnar
committed
Merge tag 'perf-core-for-mingo-5.1-20190307' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/core changes from Arnaldo Carvalho de Melo: perf bpf: Arnaldo Carvalho de Melo: - Automatically add BTF ELF markers to 'perf trace' BPF programs, so that tools such as 'bpftool map dump' can pretty print map keys and values. perf c2c: Jiri Olsa: - Fix report for empty NUMA node. perf diff: Jin Yao: - Support --time, --cpu, --pid and --tid filter options. perf probe: Arnaldo Carvalho de Melo: - Clarify error message about not finding kernel modules debuginfo. perf record: Jiri Olsa: - Fixup probing for max attr.precise_ip. perf trace: Arnaldo Carvalho de Melo: - Add missing %s lost in the 'msg_flags' recvmmsg arg when adding prefix suppression logic. perf annotate: Arnaldo Carvalho de Melo: - Calculate the max instruction name, align column to that, removing the hardcoded max 6 chars and cope with instructions with names longer than that, such as vpmovmskb, vpcmpeqb, etc. kernel: Song Liu: - Consider events with attr.bpf_event set as side-band. Gustavo A. R. Silva: - Mark expected switch fall-through in perf_event_parse_addr_filter(). Libraries: Jiri Olsa: - Fix leaks and double frees on error paths. libtraceevent: Tony Jones: - Fix buffer overflow in arg_eval(). python scripting: Tony Jones: - More python3 fixes. Trivial: Yang Wei: - Remove needless extra semicolon in clang C++ glue code. Intel PT/BTS: Adrian Hunter: - Improve auxtrace address filter error message when there is no DSO. - Fix divide by zero when TSC is not available. - Further improvements to the export to sqlite/posgresql python scripts and to the GUI sqlviewer, exporting 'parent_id' so that we have enable the creation of call trees. Andi Kleen: - Generalize function to copy from thread addr space from intel-bts code. Signed-off-by: Arnaldo Carvalho de Melo <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
2 parents 43aa378 + b8f7d86 commit b339da4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+977
-448
lines changed

kernel/events/core.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4238,7 +4238,8 @@ static bool is_sb_event(struct perf_event *event)
42384238
if (attr->mmap || attr->mmap_data || attr->mmap2 ||
42394239
attr->comm || attr->comm_exec ||
42404240
attr->task || attr->ksymbol ||
4241-
attr->context_switch)
4241+
attr->context_switch ||
4242+
attr->bpf_event)
42424243
return true;
42434244
return false;
42444245
}

tools/lib/traceevent/event-parse.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2457,7 +2457,7 @@ static int arg_num_eval(struct tep_print_arg *arg, long long *val)
24572457
static char *arg_eval (struct tep_print_arg *arg)
24582458
{
24592459
long long val;
2460-
static char buf[20];
2460+
static char buf[24];
24612461

24622462
switch (arg->type) {
24632463
case TEP_PRINT_ATOM:

tools/perf/Documentation/perf-diff.txt

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,62 @@ OPTIONS
118118
sum of shown entries will be always 100%. "absolute" means it retains
119119
the original value before and after the filter is applied.
120120

121+
--time::
122+
Analyze samples within given time window. It supports time
123+
percent with multiple time ranges. Time string is 'a%/n,b%/m,...'
124+
or 'a%-b%,c%-%d,...'.
125+
126+
For example:
127+
128+
Select the second 10% time slice to diff:
129+
130+
perf diff --time 10%/2
131+
132+
Select from 0% to 10% time slice to diff:
133+
134+
perf diff --time 0%-10%
135+
136+
Select the first and the second 10% time slices to diff:
137+
138+
perf diff --time 10%/1,10%/2
139+
140+
Select from 0% to 10% and 30% to 40% slices to diff:
141+
142+
perf diff --time 0%-10%,30%-40%
143+
144+
It also supports analyzing samples within a given time window
145+
<start>,<stop>. Times have the format seconds.microseconds. If 'start'
146+
is not given (i.e., time string is ',x.y') then analysis starts at
147+
the beginning of the file. If stop time is not given (i.e, time
148+
string is 'x.y,') then analysis goes to the end of the file. Time string is
149+
'a1.b1,c1.d1:a2.b2,c2.d2'. Use ':' to separate timestamps for different
150+
perf.data files.
151+
152+
For example, we get the timestamp information from 'perf script'.
153+
154+
perf script -i perf.data.old
155+
mgen 13940 [000] 3946.361400: ...
156+
157+
perf script -i perf.data
158+
mgen 13940 [000] 3971.150589 ...
159+
160+
perf diff --time 3946.361400,:3971.150589,
161+
162+
It analyzes the perf.data.old from the timestamp 3946.361400 to
163+
the end of perf.data.old and analyzes the perf.data from the
164+
timestamp 3971.150589 to the end of perf.data.
165+
166+
--cpu:: Only diff samples for the list of CPUs provided. Multiple CPUs can
167+
be provided as a comma-separated list with no space: 0,1. Ranges of
168+
CPUs are specified with -: 0-2. Default is to report samples on all
169+
CPUs.
170+
171+
--pid=::
172+
Only diff samples for given process ID (comma separated list).
173+
174+
--tid=::
175+
Only diff samples for given thread ID (comma separated list).
176+
121177
COMPARISON
122178
----------
123179
The comparison is governed by the baseline file. The baseline perf.data

tools/perf/arch/arm64/annotate/instructions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ static int arm64_mov__parse(struct arch *arch __maybe_unused,
5858
}
5959

6060
static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
61-
struct ins_operands *ops);
61+
struct ins_operands *ops, int max_ins_name);
6262

6363
static struct ins_ops arm64_mov_ops = {
6464
.parse = arm64_mov__parse,

tools/perf/arch/s390/annotate/instructions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ static int s390_call__parse(struct arch *arch, struct ins_operands *ops,
4646
}
4747

4848
static int call__scnprintf(struct ins *ins, char *bf, size_t size,
49-
struct ins_operands *ops);
49+
struct ins_operands *ops, int max_ins_name);
5050

5151
static struct ins_ops s390_call_ops = {
5252
.parse = s390_call__parse,

tools/perf/builtin-c2c.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2056,6 +2056,12 @@ static int setup_nodes(struct perf_session *session)
20562056
if (!set)
20572057
return -ENOMEM;
20582058

2059+
nodes[node] = set;
2060+
2061+
/* empty node, skip */
2062+
if (cpu_map__empty(map))
2063+
continue;
2064+
20592065
for (cpu = 0; cpu < map->nr; cpu++) {
20602066
set_bit(map->map[cpu], set);
20612067

@@ -2064,8 +2070,6 @@ static int setup_nodes(struct perf_session *session)
20642070

20652071
cpu2node[map->map[cpu]] = node;
20662072
}
2067-
2068-
nodes[node] = set;
20692073
}
20702074

20712075
setup_nodes_header();

tools/perf/builtin-diff.c

Lines changed: 154 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,21 @@
1919
#include "util/util.h"
2020
#include "util/data.h"
2121
#include "util/config.h"
22+
#include "util/time-utils.h"
2223

2324
#include <errno.h>
2425
#include <inttypes.h>
2526
#include <stdlib.h>
2627
#include <math.h>
2728

29+
struct perf_diff {
30+
struct perf_tool tool;
31+
const char *time_str;
32+
struct perf_time_interval *ptime_range;
33+
int range_size;
34+
int range_num;
35+
};
36+
2837
/* Diff command specific HPP columns. */
2938
enum {
3039
PERF_HPP_DIFF__BASELINE,
@@ -74,6 +83,9 @@ static unsigned int sort_compute = 1;
7483
static s64 compute_wdiff_w1;
7584
static s64 compute_wdiff_w2;
7685

86+
static const char *cpu_list;
87+
static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
88+
7789
enum {
7890
COMPUTE_DELTA,
7991
COMPUTE_RATIO,
@@ -323,22 +335,33 @@ static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair,
323335
return -1;
324336
}
325337

326-
static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
338+
static int diff__process_sample_event(struct perf_tool *tool,
327339
union perf_event *event,
328340
struct perf_sample *sample,
329341
struct perf_evsel *evsel,
330342
struct machine *machine)
331343
{
344+
struct perf_diff *pdiff = container_of(tool, struct perf_diff, tool);
332345
struct addr_location al;
333346
struct hists *hists = evsel__hists(evsel);
334347
int ret = -1;
335348

349+
if (perf_time__ranges_skip_sample(pdiff->ptime_range, pdiff->range_num,
350+
sample->time)) {
351+
return 0;
352+
}
353+
336354
if (machine__resolve(machine, &al, sample) < 0) {
337355
pr_warning("problem processing %d event, skipping it.\n",
338356
event->header.type);
339357
return -1;
340358
}
341359

360+
if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) {
361+
ret = 0;
362+
goto out_put;
363+
}
364+
342365
if (!hists__add_entry(hists, &al, NULL, NULL, NULL, sample, true)) {
343366
pr_warning("problem incrementing symbol period, skipping event\n");
344367
goto out_put;
@@ -359,17 +382,19 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
359382
return ret;
360383
}
361384

362-
static struct perf_tool tool = {
363-
.sample = diff__process_sample_event,
364-
.mmap = perf_event__process_mmap,
365-
.mmap2 = perf_event__process_mmap2,
366-
.comm = perf_event__process_comm,
367-
.exit = perf_event__process_exit,
368-
.fork = perf_event__process_fork,
369-
.lost = perf_event__process_lost,
370-
.namespaces = perf_event__process_namespaces,
371-
.ordered_events = true,
372-
.ordering_requires_timestamps = true,
385+
static struct perf_diff pdiff = {
386+
.tool = {
387+
.sample = diff__process_sample_event,
388+
.mmap = perf_event__process_mmap,
389+
.mmap2 = perf_event__process_mmap2,
390+
.comm = perf_event__process_comm,
391+
.exit = perf_event__process_exit,
392+
.fork = perf_event__process_fork,
393+
.lost = perf_event__process_lost,
394+
.namespaces = perf_event__process_namespaces,
395+
.ordered_events = true,
396+
.ordering_requires_timestamps = true,
397+
},
373398
};
374399

375400
static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
@@ -771,26 +796,127 @@ static void data__free(struct data__file *d)
771796
}
772797
}
773798

799+
static int abstime_str_dup(char **pstr)
800+
{
801+
char *str = NULL;
802+
803+
if (pdiff.time_str && strchr(pdiff.time_str, ':')) {
804+
str = strdup(pdiff.time_str);
805+
if (!str)
806+
return -ENOMEM;
807+
}
808+
809+
*pstr = str;
810+
return 0;
811+
}
812+
813+
static int parse_absolute_time(struct data__file *d, char **pstr)
814+
{
815+
char *p = *pstr;
816+
int ret;
817+
818+
/*
819+
* Absolute timestamp for one file has the format: a.b,c.d
820+
* For multiple files, the format is: a.b,c.d:a.b,c.d
821+
*/
822+
p = strchr(*pstr, ':');
823+
if (p) {
824+
if (p == *pstr) {
825+
pr_err("Invalid time string\n");
826+
return -EINVAL;
827+
}
828+
829+
*p = 0;
830+
p++;
831+
if (*p == 0) {
832+
pr_err("Invalid time string\n");
833+
return -EINVAL;
834+
}
835+
}
836+
837+
ret = perf_time__parse_for_ranges(*pstr, d->session,
838+
&pdiff.ptime_range,
839+
&pdiff.range_size,
840+
&pdiff.range_num);
841+
if (ret < 0)
842+
return ret;
843+
844+
if (!p || *p == 0)
845+
*pstr = NULL;
846+
else
847+
*pstr = p;
848+
849+
return ret;
850+
}
851+
852+
static int parse_percent_time(struct data__file *d)
853+
{
854+
int ret;
855+
856+
ret = perf_time__parse_for_ranges(pdiff.time_str, d->session,
857+
&pdiff.ptime_range,
858+
&pdiff.range_size,
859+
&pdiff.range_num);
860+
return ret;
861+
}
862+
863+
static int parse_time_str(struct data__file *d, char *abstime_ostr,
864+
char **pabstime_tmp)
865+
{
866+
int ret = 0;
867+
868+
if (abstime_ostr)
869+
ret = parse_absolute_time(d, pabstime_tmp);
870+
else if (pdiff.time_str)
871+
ret = parse_percent_time(d);
872+
873+
return ret;
874+
}
875+
774876
static int __cmd_diff(void)
775877
{
776878
struct data__file *d;
777-
int ret = -EINVAL, i;
879+
int ret, i;
880+
char *abstime_ostr, *abstime_tmp;
881+
882+
ret = abstime_str_dup(&abstime_ostr);
883+
if (ret)
884+
return ret;
885+
886+
abstime_tmp = abstime_ostr;
887+
ret = -EINVAL;
778888

779889
data__for_each_file(i, d) {
780-
d->session = perf_session__new(&d->data, false, &tool);
890+
d->session = perf_session__new(&d->data, false, &pdiff.tool);
781891
if (!d->session) {
782892
pr_err("Failed to open %s\n", d->data.path);
783893
ret = -1;
784894
goto out_delete;
785895
}
786896

897+
if (pdiff.time_str) {
898+
ret = parse_time_str(d, abstime_ostr, &abstime_tmp);
899+
if (ret < 0)
900+
goto out_delete;
901+
}
902+
903+
if (cpu_list) {
904+
ret = perf_session__cpu_bitmap(d->session, cpu_list,
905+
cpu_bitmap);
906+
if (ret < 0)
907+
goto out_delete;
908+
}
909+
787910
ret = perf_session__process_events(d->session);
788911
if (ret) {
789912
pr_err("Failed to process %s\n", d->data.path);
790913
goto out_delete;
791914
}
792915

793916
perf_evlist__collapse_resort(d->session->evlist);
917+
918+
if (pdiff.ptime_range)
919+
zfree(&pdiff.ptime_range);
794920
}
795921

796922
data_process();
@@ -802,6 +928,13 @@ static int __cmd_diff(void)
802928
}
803929

804930
free(data__files);
931+
932+
if (pdiff.ptime_range)
933+
zfree(&pdiff.ptime_range);
934+
935+
if (abstime_ostr)
936+
free(abstime_ostr);
937+
805938
return ret;
806939
}
807940

@@ -849,6 +982,13 @@ static const struct option options[] = {
849982
OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."),
850983
OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
851984
"How to display percentage of filtered entries", parse_filter_percentage),
985+
OPT_STRING(0, "time", &pdiff.time_str, "str",
986+
"Time span (time percent or absolute timestamp)"),
987+
OPT_STRING(0, "cpu", &cpu_list, "cpu", "list of cpus to profile"),
988+
OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
989+
"only consider symbols in these pids"),
990+
OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
991+
"only consider symbols in these tids"),
852992
OPT_END()
853993
};
854994

0 commit comments

Comments
 (0)