fast_stack 0.0.2 → 0.0.3
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/README.md +22 -0
- data/lib/fast_stack.rb +42 -2
- data/spec/fast_stack_spec.rb +0 -2
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7b203e805558207a896a66af413dfbbf48fbf0d
|
4
|
+
data.tar.gz: f8aaa3a556df3007d936e21c7983512ab04f1eea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6eef1b4399175be510fc9a93c5948d0791b6d2139b3da100cbecd39fabe1fb3d33397d198faf91d2218fe6e20570e843dd71de9478f5fd2430cc8b6da21c7b02
|
7
|
+
data.tar.gz: fd2f07f355adb448f7feeeb716a5c9f748d9fccfe1baf9ad26bebea1bf9ff0894ea7eaddd61bd37a18f9d66aa19ed324e6308061d47ebcf9841bb7d21788cc09
|
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
### Fast stack
|
2
2
|
|
3
|
+
Very efficient collection of ruby backtraces, even under heavy CPU load
|
3
4
|
|
4
5
|
### How do you use it?
|
5
6
|
|
@@ -8,4 +9,25 @@
|
|
8
9
|
### Usage
|
9
10
|
|
10
11
|
|
12
|
+
```
|
13
|
+
def fib( n )
|
14
|
+
return n if ( 0..1 ).include? n
|
15
|
+
( fib( n - 1 ) + fib( n - 2 ) )
|
16
|
+
end
|
17
|
+
|
18
|
+
stacks = FastStack.profile do
|
19
|
+
fib(30)
|
20
|
+
end
|
21
|
+
|
22
|
+
puts stacks.count
|
23
|
+
# 30
|
24
|
+
|
25
|
+
```
|
26
|
+
|
27
|
+
### Notes
|
28
|
+
|
29
|
+
This technique was conceived by https://github.com/tmm1 , big thank you.
|
30
|
+
|
31
|
+
Ruby 2.0 uses #backtrace_locations, 1.9.3 uses #backtrace
|
32
|
+
|
11
33
|
(gem template based on https://github.com/CodeMonkeySteve/fast_xor )
|
data/lib/fast_stack.rb
CHANGED
@@ -1,14 +1,54 @@
|
|
1
1
|
require 'fast_stack/fast_stack'
|
2
2
|
module FastStack
|
3
3
|
def self.profile(millisecs=1, &blk)
|
4
|
+
done = false
|
4
5
|
stacks = []
|
5
6
|
thread = Thread.current
|
7
|
+
delta = millisecs / 1000.0
|
8
|
+
last_time = Time.new
|
9
|
+
|
10
|
+
new_api = thread.respond_to?(:backtrace_locations)
|
11
|
+
|
12
|
+
# NOTE not extracting to another method to avoid adding a frame
|
13
|
+
# to the stack
|
14
|
+
|
15
|
+
# this thread catches stuff fast stack does not
|
16
|
+
# the main case is catching sleeping threads
|
17
|
+
profile_thread = Thread.new do
|
18
|
+
until done
|
19
|
+
start = Time.new
|
20
|
+
if last_time < start - delta
|
21
|
+
last_time = start
|
22
|
+
stacks << (new_api ? thread.backtrace_locations : thread.backtrace)
|
23
|
+
end
|
24
|
+
|
25
|
+
sleep(delta)
|
26
|
+
end
|
27
|
+
end
|
6
28
|
|
7
29
|
trap('PROF') do
|
8
|
-
|
30
|
+
start = Time.new
|
31
|
+
if last_time < start - delta
|
32
|
+
last_time = start
|
33
|
+
stack = (new_api ? thread.backtrace_locations : thread.backtrace)
|
34
|
+
# I am not sure if this is ensured to run in the thread
|
35
|
+
# though in my samples it does
|
36
|
+
if thread == Thread.current
|
37
|
+
stack = stack[2..-1]
|
38
|
+
# since we are in the same thread, might as well remove
|
39
|
+
# our overhead
|
40
|
+
start = Time.new
|
41
|
+
end
|
42
|
+
stacks << stack
|
43
|
+
end
|
9
44
|
end
|
10
45
|
|
11
|
-
|
46
|
+
begin
|
47
|
+
profile_block(millisecs * 1000, &blk)
|
48
|
+
ensure
|
49
|
+
done = true
|
50
|
+
profile_thread.join
|
51
|
+
end
|
12
52
|
|
13
53
|
stacks
|
14
54
|
end
|
data/spec/fast_stack_spec.rb
CHANGED