perf2pprof 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []