range-perf.pl 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #!/usr/bin/perl -w
  2. #
  3. # range-perf Extract a time range from Linux "perf script" output.
  4. #
  5. # USAGE EXAMPLE:
  6. #
  7. # perf record -F 100 -a -- sleep 60
  8. # perf script | ./perf2range.pl 10 20 # range 10 to 20 seconds only
  9. # perf script | ./perf2range.pl 0 0.5 # first half second only
  10. #
  11. # MAKING A SERIES OF FLAME GRAPHS:
  12. #
  13. # Let's say you had the output of "perf script" in a file, out.stacks01, which
  14. # was for a 180 second profile. The following command creates a series of
  15. # flame graphs for each 10 second interval:
  16. #
  17. # for i in `seq 0 10 170`; do cat out.stacks01 | \
  18. # ./perf2range.pl $i $((i + 10)) | ./stackcollapse-perf.pl | \
  19. # grep -v cpu_idle | ./flamegraph.pl --hash --color=java \
  20. # --title="range $i $((i + 10))" > out.range_$i.svg; echo $i done; done
  21. #
  22. # In that example, I used "--color=java" for the Java palette, and excluded
  23. # the idle CPU task. Customize as needed.
  24. #
  25. # Copyright 2017 Netflix, Inc.
  26. # Licensed under the Apache License, Version 2.0 (the "License")
  27. #
  28. # 21-Feb-2017 Brendan Gregg Created this.
  29. use strict;
  30. use Getopt::Long;
  31. use POSIX 'floor';
  32. sub usage {
  33. die <<USAGE_END;
  34. USAGE: $0 [options] min_seconds max_seconds
  35. --timeraw # use raw timestamps from perf
  36. --timezerosecs # time starts at 0 secs, but keep offset from perf
  37. eg,
  38. $0 10 20 # only include samples between 10 and 20 seconds
  39. USAGE_END
  40. }
  41. my $timeraw = 0;
  42. my $timezerosecs = 0;
  43. GetOptions(
  44. 'timeraw' => \$timeraw,
  45. 'timezerosecs' => \$timezerosecs,
  46. ) or usage();
  47. if (@ARGV < 2 || $ARGV[0] eq "-h" || $ARGV[0] eq "--help") {
  48. usage();
  49. exit;
  50. }
  51. my $begin = $ARGV[0];
  52. my $end = $ARGV[1];
  53. #
  54. # Parsing
  55. #
  56. # IP only examples:
  57. #
  58. # java 52025 [026] 99161.926202: cycles:
  59. # java 14341 [016] 252732.474759: cycles: 7f36571947c0 nmethod::is_nmethod() const (/...
  60. # java 14514 [022] 28191.353083: cpu-clock: 7f92b4fdb7d4 Ljava_util_List$size$0;::call (/tmp/perf-11936.map)
  61. # swapper 0 [002] 6035557.056977: 10101010 cpu-clock: ffffffff810013aa xen_hypercall_sched_op+0xa (/lib/modules/4.9-virtual/build/vmlinux)
  62. # bash 25370 603are 6036.991603: 10101010 cpu-clock: 4b931e [unknown] (/bin/bash)
  63. # bash 25370/25370 6036036.799684: cpu-clock: 4b913b [unknown] (/bin/bash)
  64. # other combinations are possible.
  65. #
  66. # Stack examples (-g):
  67. #
  68. # swapper 0 [021] 28648.467059: cpu-clock:
  69. # ffffffff810013aa xen_hypercall_sched_op ([kernel.kallsyms])
  70. # ffffffff8101cb2f default_idle ([kernel.kallsyms])
  71. # ffffffff8101d406 arch_cpu_idle ([kernel.kallsyms])
  72. # ffffffff810bf475 cpu_startup_entry ([kernel.kallsyms])
  73. # ffffffff81010228 cpu_bringup_and_idle ([kernel.kallsyms])
  74. #
  75. # java 14375 [022] 28648.467079: cpu-clock:
  76. # 7f92bdd98965 Ljava/io/OutputStream;::write (/tmp/perf-11936.map)
  77. # 7f8808cae7a8 [unknown] ([unknown])
  78. #
  79. # swapper 0 [005] 5076.836336: cpu-clock:
  80. # ffffffff81051586 native_safe_halt ([kernel.kallsyms])
  81. # ffffffff8101db4f default_idle ([kernel.kallsyms])
  82. # ffffffff8101e466 arch_cpu_idle ([kernel.kallsyms])
  83. # ffffffff810c2b31 cpu_startup_entry ([kernel.kallsyms])
  84. # ffffffff810427cd start_secondary ([kernel.kallsyms])
  85. #
  86. # swapper 0 [002] 6034779.719110: 10101010 cpu-clock:
  87. # 2013aa xen_hypercall_sched_op+0xfe20000a (/lib/modules/4.9-virtual/build/vmlinux)
  88. # a72f0e default_idle+0xfe20001e (/lib/modules/4.9-virtual/build/vmlinux)
  89. # 2392bf arch_cpu_idle+0xfe20000f (/lib/modules/4.9-virtual/build/vmlinux)
  90. # a73333 default_idle_call+0xfe200023 (/lib/modules/4.9-virtual/build/vmlinux)
  91. # 2c91a4 cpu_startup_entry+0xfe2001c4 (/lib/modules/4.9-virtual/build/vmlinux)
  92. # 22b64a cpu_bringup_and_idle+0xfe20002a (/lib/modules/4.9-virtual/build/vmlinux)
  93. #
  94. # bash 25370/25370 6035935.188539: cpu-clock:
  95. # b9218 [unknown] (/bin/bash)
  96. # 2037fe8 [unknown] ([unknown])
  97. # other combinations are possible.
  98. #
  99. # This regexp matches the event line, and puts time in $1, and the event name
  100. # in $2:
  101. #
  102. my $event_regexp = qr/ +([0-9\.]+): *\S* *(\S+):/;
  103. my $line;
  104. my $start = 0;
  105. my $ok = 0;
  106. my $time;
  107. while (1) {
  108. $line = <STDIN>;
  109. last unless defined $line;
  110. next if $line =~ /^#/; # skip comments
  111. if ($line =~ $event_regexp) {
  112. my ($ts, $event) = ($1, $2, $3);
  113. $start = $ts if $start == 0;
  114. if ($timezerosecs) {
  115. $time = $ts - floor($start);
  116. } elsif (!$timeraw) {
  117. $time = $ts - $start;
  118. } else {
  119. $time = $ts; # raw times
  120. }
  121. $ok = 1 if $time >= $begin;
  122. # assume samples are in time order:
  123. exit if $time > $end;
  124. }
  125. print $line if $ok;
  126. }