perf2pprof 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/COPYING +1 -0
- data/README +14 -0
- data/perf2pprof +125 -0
- 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: []
|