perf2pprof 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +1 -0
  3. data/README +14 -0
  4. data/perf2pprof +125 -0
  5. metadata +50 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9603c69d125a72fa9ad90e475162a41a861b17a8
4
+ data.tar.gz: 3637ac300f2cdb6432aec33a0075ae175d019ba3
5
+ SHA512:
6
+ metadata.gz: 010522490230e336f1d95f07b43b7aa8362790f0105fb8df1c048d428d723bde242245d3c403a3408572bb55018fc74ba536c28044d24ebe006308e41c8ba889
7
+ data.tar.gz: 44d00a91553923573d3d7cc980a34527e0af3684468c19f3ae79edf82132b1107df86c521aa31d2ee5f4bf02bc42dfd70ce9f7f08f05e986bd0f152a459481e7
data/COPYING ADDED
@@ -0,0 +1 @@
1
+ This is public domain.
data/README ADDED
@@ -0,0 +1,14 @@
1
+ perf2pprof converts perf record output to gperftools CPU profile
2
+ format for analysis and visualization using excellent pprof tool.
3
+
4
+ Example:
5
+ ---------
6
+
7
+ # perf record --call-graph dwarf ./slow-words-count </usr/share/dic/words
8
+
9
+ # perf2pprof --web
10
+
11
+ (or)
12
+
13
+ # perf2pprof --output slow-words-count.prof
14
+ # pprof --gv ./slow-words-count slow-words-count.prof
data/perf2pprof ADDED
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'set'
4
+ require 'optparse'
5
+ require 'ostruct'
6
+ require 'tempfile'
7
+ require 'shellwords'
8
+
9
+ MMAPRE = /PERF_RECORD_MMAP2.*?\[(.*?)\((.*)\) @ (\S+).*\]:\s+(\S+)\s+(.+)/
10
+ STACKRE = /\A\s+([0-9A-Fa-f]+)/
11
+
12
+ class Converter
13
+ attr_reader :first_map
14
+
15
+ def read(inp)
16
+ maps = Set.new
17
+ first_map = nil
18
+
19
+ all_stacks = []
20
+
21
+ inp.each_line do |line|
22
+ while true
23
+ line.chomp!
24
+ if line =~ /\A\S/
25
+ if line =~ MMAPRE
26
+ addr, size, off, rxp, rest = $1.to_i(0), $2.to_i(0), $3.to_i(0), $4, $5
27
+ m = [addr, size, off, rxp, rest]
28
+ first_map = m unless first_map
29
+ maps << m
30
+ end
31
+ elsif line !~ /^$/
32
+ raise "unexpected: #{line}" unless line =~ STACKRE
33
+ stack = [$1.to_i(16)+1]
34
+ while (line = inp.gets)
35
+ break unless line =~ STACKRE
36
+ stack << $1.to_i(16)
37
+ end
38
+ all_stacks << stack
39
+ next if line
40
+ end
41
+ break
42
+ end
43
+ end
44
+ @all_stacks = all_stacks
45
+ @maps = maps
46
+ @first_map = first_map
47
+ self
48
+ end
49
+
50
+ def self.read(inp)
51
+ self.new.read(inp)
52
+ end
53
+
54
+ def write(outp)
55
+ procmaps = ""
56
+ @maps.to_a.sort.each do |(addr, size, off, rxp, rest)|
57
+ procmaps << "#{addr.to_s(16)}-#{(addr+size).to_s(16)} #{rxp} #{off.to_s(16)} 00:00 0 #{rest}\n"
58
+ end
59
+
60
+ # this is 64-bit cpu-profile header for pprof
61
+ hdr = %w[0x00000 0x00000 0x00003 0x00000
62
+ 0x00000 0x00000 0x02710 0x00000
63
+ 0x00000 0x00000].map {|s| s.to_i(0)}.pack("L<*")
64
+
65
+ outp.print hdr
66
+
67
+ @all_stacks.each do |stack|
68
+ s = stack.size
69
+ newstack = [1, s, *stack]
70
+ outp.print(newstack.pack("Q<*"))
71
+ end
72
+
73
+ outp.print([0, 1, 0].pack("Q<*"))
74
+
75
+ outp.print procmaps
76
+ end
77
+
78
+ end
79
+
80
+ def parse_options!
81
+ opts = OpenStruct.new
82
+ opts.perf_template = "perf script -i %s --show-mmap-events"
83
+ opts.web = false
84
+ opts.perf_data = "perf.data"
85
+ opts.opath = nil
86
+
87
+ OptionParser.new do |op|
88
+ op.on("-p", "--perf-template STRING",
89
+ "perf invokation template (#{opts.pprof_template})") do |val|
90
+ opts.perf_template = val
91
+ end
92
+ op.on("--web") do
93
+ opts.web = true
94
+ end
95
+ op.on("-i", "--input PATH", "override input file to perf (perf.data)") do |path|
96
+ opts.perf_data = path
97
+ end
98
+ op.on("-o", "--output PATH", "pprof cpu profile to output") do |path|
99
+ opts.opath = path
100
+ end
101
+ end.parse!(ARGV)
102
+ opts
103
+ end
104
+
105
+ opts = parse_options!
106
+
107
+ if (opts.web && opts.opath) || (!opts.web && !opts.opath)
108
+ puts "exactly one of --web and --output must be given"
109
+ Process.exit(1)
110
+ end
111
+
112
+ c = IO.popen(opts.perf_template % [Shellwords.escape(opts.perf_data)], "r") do |f|
113
+ Converter.read f
114
+ end
115
+
116
+ if opts.web
117
+ temp = Tempfile.new("pprof-conv")
118
+ c.write(temp)
119
+ temp.close
120
+ pprof = ENV["PPROF_PATH"] || "pprof"
121
+ args = [pprof, "--web", c.first_map.last, temp.path]
122
+ p system(*args)
123
+ else
124
+ c.write(File.open(opts.opath, "w"))
125
+ end
metadata ADDED
@@ -0,0 +1,50 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: perf2pprof
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - Aliaksey Kandratsenka
8
+ autorequire:
9
+ bindir: "./"
10
+ cert_chain: []
11
+ date: 2015-02-15 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: |
14
+ perf2pprof converts perf record output to gperftools CPU profile
15
+ format for analysis and visualization using excellent pprof tool.
16
+ email: alk@tut.by
17
+ executables:
18
+ - perf2pprof
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - "./perf2pprof"
23
+ - COPYING
24
+ - README
25
+ - perf2pprof
26
+ homepage: https://github.com/alk/perf2pprof
27
+ licenses:
28
+ - public domain
29
+ metadata: {}
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubyforge_project:
46
+ rubygems_version: 2.2.2
47
+ signing_key:
48
+ specification_version: 4
49
+ summary: perf2pprof is adaptor from perf profiles to pprof tool
50
+ test_files: []