builtin-trace.c (efd5745e43f3aabd95d521289e0caa0e30668cf4) builtin-trace.c (1302d88e66f12a7b46a5598e641d93f0713007e0)
1#include "builtin.h"
2#include "util/color.h"
3#include "util/evlist.h"
4#include "util/machine.h"
5#include "util/thread.h"
6#include "util/parse-options.h"
7#include "util/thread_map.h"
8#include "event-parse.h"

--- 55 unchanged lines hidden (view full) ---

64}
65
66struct thread_trace {
67 u64 entry_time;
68 u64 exit_time;
69 bool entry_pending;
70 unsigned long nr_events;
71 char *entry_str;
1#include "builtin.h"
2#include "util/color.h"
3#include "util/evlist.h"
4#include "util/machine.h"
5#include "util/thread.h"
6#include "util/parse-options.h"
7#include "util/thread_map.h"
8#include "event-parse.h"

--- 55 unchanged lines hidden (view full) ---

64}
65
66struct thread_trace {
67 u64 entry_time;
68 u64 exit_time;
69 bool entry_pending;
70 unsigned long nr_events;
71 char *entry_str;
72 double runtime_ms;
72};
73
74static struct thread_trace *thread_trace__new(void)
75{
76 return zalloc(sizeof(struct thread_trace));
77}
78
79static struct thread_trace *thread__trace(struct thread *thread)

--- 24 unchanged lines hidden (view full) ---

104 struct {
105 int max;
106 struct syscall *table;
107 } syscalls;
108 struct perf_record_opts opts;
109 struct machine host;
110 u64 base_time;
111 unsigned long nr_events;
73};
74
75static struct thread_trace *thread_trace__new(void)
76{
77 return zalloc(sizeof(struct thread_trace));
78}
79
80static struct thread_trace *thread__trace(struct thread *thread)

--- 24 unchanged lines hidden (view full) ---

105 struct {
106 int max;
107 struct syscall *table;
108 } syscalls;
109 struct perf_record_opts opts;
110 struct machine host;
111 u64 base_time;
112 unsigned long nr_events;
113 bool sched;
112 bool multiple_threads;
113 double duration_filter;
114 bool multiple_threads;
115 double duration_filter;
116 double runtime_ms;
114};
115
116static bool trace__filter_duration(struct trace *trace, double t)
117{
118 return t < (trace->duration_filter * NSEC_PER_MSEC);
119}
120
121static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)

--- 262 unchanged lines hidden (view full) ---

384
385 putchar('\n');
386out:
387 ttrace->entry_pending = false;
388
389 return 0;
390}
391
117};
118
119static bool trace__filter_duration(struct trace *trace, double t)
120{
121 return t < (trace->duration_filter * NSEC_PER_MSEC);
122}
123
124static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)

--- 262 unchanged lines hidden (view full) ---

387
388 putchar('\n');
389out:
390 ttrace->entry_pending = false;
391
392 return 0;
393}
394
395static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
396 struct perf_sample *sample)
397{
398 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
399 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
400 struct thread *thread = machine__findnew_thread(&trace->host, sample->tid);
401 struct thread_trace *ttrace = thread__trace(thread);
402
403 if (ttrace == NULL)
404 goto out_dump;
405
406 ttrace->runtime_ms += runtime_ms;
407 trace->runtime_ms += runtime_ms;
408 return 0;
409
410out_dump:
411 printf("%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
412 evsel->name,
413 perf_evsel__strval(evsel, sample, "comm"),
414 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
415 runtime,
416 perf_evsel__intval(evsel, sample, "vruntime"));
417 return 0;
418}
419
392static int trace__run(struct trace *trace, int argc, const char **argv)
393{
394 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
395 struct perf_evsel *evsel;
396 int err = -1, i;
397 unsigned long before;
398 const bool forks = argc > 0;
399
400 if (evlist == NULL) {
401 printf("Not enough memory to run!\n");
402 goto out;
403 }
404
405 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
406 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
407 printf("Couldn't read the raw_syscalls tracepoints information!\n");
408 goto out_delete_evlist;
409 }
410
420static int trace__run(struct trace *trace, int argc, const char **argv)
421{
422 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
423 struct perf_evsel *evsel;
424 int err = -1, i;
425 unsigned long before;
426 const bool forks = argc > 0;
427
428 if (evlist == NULL) {
429 printf("Not enough memory to run!\n");
430 goto out;
431 }
432
433 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
434 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
435 printf("Couldn't read the raw_syscalls tracepoints information!\n");
436 goto out_delete_evlist;
437 }
438
439 if (trace->sched &&
440 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
441 trace__sched_stat_runtime)) {
442 printf("Couldn't read the sched_stat_runtime tracepoint information!\n");
443 goto out_delete_evlist;
444 }
445
411 err = perf_evlist__create_maps(evlist, &trace->opts.target);
412 if (err < 0) {
413 printf("Problems parsing the target to trace, check your options!\n");
414 goto out_delete_evlist;
415 }
416
417 err = trace__symbols_init(trace, evlist);
418 if (err < 0) {

--- 97 unchanged lines hidden (view full) ---

516 goto again;
517
518out_delete_evlist:
519 perf_evlist__delete(evlist);
520out:
521 return err;
522}
523
446 err = perf_evlist__create_maps(evlist, &trace->opts.target);
447 if (err < 0) {
448 printf("Problems parsing the target to trace, check your options!\n");
449 goto out_delete_evlist;
450 }
451
452 err = trace__symbols_init(trace, evlist);
453 if (err < 0) {

--- 97 unchanged lines hidden (view full) ---

551 goto again;
552
553out_delete_evlist:
554 perf_evlist__delete(evlist);
555out:
556 return err;
557}
558
559static size_t trace__fprintf_threads_header(FILE *fp)
560{
561 size_t printed;
562
563 printed = fprintf(fp, "\n _____________________________________________________________________\n");
564 printed += fprintf(fp," __) Summary of events (__\n\n");
565 printed += fprintf(fp," [ task - pid ] [ events ] [ ratio ] [ runtime ]\n");
566 printed += fprintf(fp," _____________________________________________________________________\n\n");
567
568 return printed;
569}
570
571static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
572{
573 size_t printed = trace__fprintf_threads_header(fp);
574 struct rb_node *nd;
575
576 for (nd = rb_first(&trace->host.threads); nd; nd = rb_next(nd)) {
577 struct thread *thread = rb_entry(nd, struct thread, rb_node);
578 struct thread_trace *ttrace = thread->priv;
579 const char *color;
580 double ratio;
581
582 if (ttrace == NULL)
583 continue;
584
585 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
586
587 color = PERF_COLOR_NORMAL;
588 if (ratio > 50.0)
589 color = PERF_COLOR_RED;
590 else if (ratio > 25.0)
591 color = PERF_COLOR_GREEN;
592 else if (ratio > 5.0)
593 color = PERF_COLOR_YELLOW;
594
595 printed += color_fprintf(fp, color, "%20s", thread->comm);
596 printed += fprintf(fp, " - %-5d :%11lu [", thread->pid, ttrace->nr_events);
597 printed += color_fprintf(fp, color, "%5.1f%%", ratio);
598 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
599 }
600
601 return printed;
602}
603
524static int trace__set_duration(const struct option *opt, const char *str,
525 int unset __maybe_unused)
526{
527 struct trace *trace = opt->value;
528
529 trace->duration_filter = atof(str);
530 return 0;
531}

--- 34 unchanged lines hidden (view full) ---

566 "child tasks do not inherit counters"),
567 OPT_UINTEGER(0, "mmap-pages", &trace.opts.mmap_pages,
568 "number of mmap data pages"),
569 OPT_STRING(0, "uid", &trace.opts.target.uid_str, "user",
570 "user to profile"),
571 OPT_CALLBACK(0, "duration", &trace, "float",
572 "show only events with duration > N.M ms",
573 trace__set_duration),
604static int trace__set_duration(const struct option *opt, const char *str,
605 int unset __maybe_unused)
606{
607 struct trace *trace = opt->value;
608
609 trace->duration_filter = atof(str);
610 return 0;
611}

--- 34 unchanged lines hidden (view full) ---

646 "child tasks do not inherit counters"),
647 OPT_UINTEGER(0, "mmap-pages", &trace.opts.mmap_pages,
648 "number of mmap data pages"),
649 OPT_STRING(0, "uid", &trace.opts.target.uid_str, "user",
650 "user to profile"),
651 OPT_CALLBACK(0, "duration", &trace, "float",
652 "show only events with duration > N.M ms",
653 trace__set_duration),
654 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
574 OPT_END()
575 };
576 int err;
577 char bf[BUFSIZ];
578
579 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
580
581 err = perf_target__validate(&trace.opts.target);

--- 8 unchanged lines hidden (view full) ---

590 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
591 printf("%s", bf);
592 return err;
593 }
594
595 if (!argc && perf_target__none(&trace.opts.target))
596 trace.opts.target.system_wide = true;
597
655 OPT_END()
656 };
657 int err;
658 char bf[BUFSIZ];
659
660 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
661
662 err = perf_target__validate(&trace.opts.target);

--- 8 unchanged lines hidden (view full) ---

671 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
672 printf("%s", bf);
673 return err;
674 }
675
676 if (!argc && perf_target__none(&trace.opts.target))
677 trace.opts.target.system_wide = true;
678
598 return trace__run(&trace, argc, argv);
679 err = trace__run(&trace, argc, argv);
680
681 if (trace.sched && !err)
682 trace__fprintf_thread_summary(&trace, stdout);
683
684 return err;
599}
685}