sampling_prof 0.1.5 → 0.2.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.
- checksums.yaml +4 -4
- data/lib/sampling_prof.jar +0 -0
- data/lib/sampling_prof.rb +12 -19
- data/lib/sampling_prof/internal.rb +85 -37
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d1357aece706366d12fac2c1670ded8f2bdd24f
|
4
|
+
data.tar.gz: 12077ea8a42b5ca17c38df2875aab9c6234e9955
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4fd426493b203256f040399daf7e3c69e3ce44b5428d420b6d70900036cc3cd5d8910d5f2e6d16c7db5ee40894ed4f8f156a5749fd23676cb6b9055bed166586
|
7
|
+
data.tar.gz: 65c57574670f4385e0b9f68a994bc33c01766e18b4025ee768292a22a8954662e7cc58f2267dcfc9b276f8f7856f3860c9b4f77be10ef0c51ad1813a7bad01bd
|
data/lib/sampling_prof.jar
CHANGED
Binary file
|
data/lib/sampling_prof.rb
CHANGED
@@ -9,6 +9,17 @@ class SamplingProf
|
|
9
9
|
|
10
10
|
attr_writer :output_file
|
11
11
|
|
12
|
+
def initialize(sampling_interval=0.1,
|
13
|
+
multithreading=false,
|
14
|
+
output_interval=nil, #sec
|
15
|
+
&output_handler)
|
16
|
+
self.sampling_interval = sampling_interval
|
17
|
+
self.multithreading = multithreading
|
18
|
+
self.output_interval = output_interval || (multithreading ? 60 : nil)
|
19
|
+
self.output_handler = block_given? ? output_handler : default_output_handler
|
20
|
+
internal_initialize if respond_to?(:internal_initialize)
|
21
|
+
end
|
22
|
+
|
12
23
|
def output_file
|
13
24
|
@output_file ||= DEFAULT_OUTPUT_FILE
|
14
25
|
end
|
@@ -20,28 +31,10 @@ class SamplingProf
|
|
20
31
|
stop if block_given?
|
21
32
|
end
|
22
33
|
|
23
|
-
def start(handler=default_output_handler)
|
24
|
-
__start__(&handler)
|
25
|
-
end
|
26
|
-
|
27
34
|
def default_output_handler
|
28
35
|
lambda do |data|
|
29
|
-
nodes, counts, call_graph = data
|
30
36
|
File.open(output_file, 'w') do |f|
|
31
|
-
|
32
|
-
# node name, node id
|
33
|
-
f.puts node.join(',')
|
34
|
-
end
|
35
|
-
f.puts ""
|
36
|
-
counts.each do |count|
|
37
|
-
# node id, count
|
38
|
-
f.puts count.flatten.join(",")
|
39
|
-
end
|
40
|
-
f.puts ""
|
41
|
-
call_graph.each do |v|
|
42
|
-
# from node id, to node id, count
|
43
|
-
f.puts v.flatten.join(",")
|
44
|
-
end
|
37
|
+
f.write(data)
|
45
38
|
end
|
46
39
|
end
|
47
40
|
end
|
@@ -1,40 +1,47 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'thread'
|
1
3
|
|
2
4
|
class SamplingProf
|
3
|
-
class Sample < Struct.new(:self, :total)
|
4
|
-
end
|
5
|
-
|
6
5
|
class Sampling
|
7
|
-
def initialize
|
6
|
+
def initialize(threads)
|
8
7
|
@samples = Hash.new{|h,k| h[k] = [0, 0] }
|
9
8
|
@call_graph = Hash.new{|h,k| h[k] = 0}
|
10
9
|
@nodes = {}
|
10
|
+
@threads = threads
|
11
11
|
end
|
12
12
|
|
13
13
|
def result
|
14
|
-
|
14
|
+
ret = []
|
15
|
+
ret << @nodes.map {|node| node.join(',')}.join("\n")
|
16
|
+
ret << @samples.map {|count| count.flatten.join(',')}.join("\n")
|
17
|
+
ret << @call_graph.map {|v| v.flatten.join(',')}.join("\n")
|
18
|
+
"#{ret.join("\n\n")}\n"
|
15
19
|
end
|
16
20
|
|
17
|
-
def process
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
21
|
+
def process
|
22
|
+
@threads.each do |thread|
|
23
|
+
locations = thread.backtrace_locations
|
24
|
+
from = -1
|
25
|
+
paths = []
|
26
|
+
calls = []
|
27
|
+
top_index = locations.size - 1
|
28
|
+
locations.reverse.each_with_index do |loc, i|
|
29
|
+
node_id = node_id(loc)
|
30
|
+
if i == top_index
|
31
|
+
@samples[node_id][0] += 1
|
32
|
+
end
|
27
33
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
34
|
+
path = [from, node_id]
|
35
|
+
if !paths.include?(path)
|
36
|
+
paths << path
|
37
|
+
@call_graph[path] += 1
|
38
|
+
end
|
39
|
+
if !calls.include?(node_id)
|
40
|
+
calls << node_id
|
41
|
+
@samples[node_id][1] += 1
|
42
|
+
end
|
43
|
+
from = node_id
|
36
44
|
end
|
37
|
-
from = node_id
|
38
45
|
end
|
39
46
|
end
|
40
47
|
|
@@ -47,24 +54,56 @@ class SamplingProf
|
|
47
54
|
end
|
48
55
|
end
|
49
56
|
|
50
|
-
|
51
|
-
|
57
|
+
class Threads
|
58
|
+
def initialize
|
59
|
+
@set = Set.new
|
60
|
+
@mutex = Mutex.new
|
61
|
+
end
|
62
|
+
|
63
|
+
def each(&block)
|
64
|
+
dup.each(&block)
|
65
|
+
end
|
66
|
+
|
67
|
+
def dup
|
68
|
+
@mutex.synchronize { @set.dup }
|
69
|
+
end
|
70
|
+
|
71
|
+
def add(obj)
|
72
|
+
@mutex.synchronize { @set.add(obj) }
|
73
|
+
end
|
74
|
+
|
75
|
+
def delete(obj)
|
76
|
+
@mutex.synchronize { @set.delete(obj) }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
attr_accessor :sampling_interval, :multithreading, :output_interval, :output_handler
|
81
|
+
|
82
|
+
def internal_initialize
|
52
83
|
@running = false
|
53
84
|
@sampling_thread = nil
|
85
|
+
@threads = Threads.new
|
54
86
|
end
|
55
87
|
|
56
|
-
def
|
57
|
-
|
88
|
+
def start
|
89
|
+
if @multithreading || !@running
|
58
90
|
@running = true
|
59
|
-
|
60
|
-
@sampling_thread
|
61
|
-
sampling = Sampling.new
|
91
|
+
@threads.add(Thread.current)
|
92
|
+
@sampling_thread ||= Thread.start do
|
62
93
|
loop do
|
94
|
+
sampling = Sampling.new(@threads)
|
95
|
+
start_time = Time.now
|
96
|
+
loop do
|
97
|
+
break unless @running
|
98
|
+
if @multithreading
|
99
|
+
break if output_interval < (Time.now - start_time)
|
100
|
+
end
|
101
|
+
sampling.process
|
102
|
+
sleep @sampling_interval
|
103
|
+
end
|
104
|
+
@output_handler.call(sampling.result)
|
63
105
|
break unless @running
|
64
|
-
sampling.process(target.backtrace_locations)
|
65
|
-
sleep @period
|
66
106
|
end
|
67
|
-
block.call(sampling.result)
|
68
107
|
end
|
69
108
|
true
|
70
109
|
end
|
@@ -72,13 +111,22 @@ class SamplingProf
|
|
72
111
|
|
73
112
|
def stop
|
74
113
|
if @running
|
75
|
-
@
|
76
|
-
|
77
|
-
|
114
|
+
if @multithreading
|
115
|
+
@threads.delete(Thread.current)
|
116
|
+
else
|
117
|
+
terminate
|
118
|
+
end
|
78
119
|
true
|
79
120
|
end
|
80
121
|
end
|
81
122
|
|
123
|
+
def terminate
|
124
|
+
@running = false
|
125
|
+
@sampling_thread.join
|
126
|
+
@sampling_thread = nil
|
127
|
+
true
|
128
|
+
end
|
129
|
+
|
82
130
|
def profiling?
|
83
131
|
!!@sampling_thread
|
84
132
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sampling_prof
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Xiao Li
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2014-03-
|
12
|
+
date: 2014-03-23 00:00:00 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake-compiler
|