fast_stack 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 25593572df6635a6ab1e50009f6e20617dcf345d
4
- data.tar.gz: e1c7839628489bc0cc1dceb044b82c7a46493bf9
3
+ metadata.gz: 5379c5d5a7c8876efd6c43433644a7d88454afce
4
+ data.tar.gz: 5446ba4ccea259eae6264339aab38f0e72b54f74
5
5
  SHA512:
6
- metadata.gz: 82b33efbffe61e59052b109eb848697dfada7cac792f871a138c6ff83f3ca1461b4b2f47b59a4d342743e5b32a380d5db8fd524ad5ba35e2bcde4c4870310c0b
7
- data.tar.gz: 910abe7607c9e1c96ee7444e3a2e9f83c4d88b693385416bed5088a71b84e2d423bfd2faaf19065e173b9a6fc445a0d76d07070be483b00867747e0704742425
6
+ metadata.gz: a92d6aefd51e5effae3d804934218e6c3f74a71d3f8268792f44a2a2722d3b6f1639a873111ff31c532b8ae03b4e7aac94650decea798fe060e5070e4b6c2d41
7
+ data.tar.gz: d350f9fd8154e9d78f6934b687fbefd975706788b723266bff4bffa4469c01ab3e32fb615bc101bd4ec41bd4a03ebda9a10b68737760a6e2079e51d36b059bf4
data/MIT-LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- Copyright (c) 2006-2009 Steve Sloan
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
-
1
+ Copyright (c) 2006-2009 Steve Sloan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README.md CHANGED
@@ -1,37 +1,32 @@
1
- ### Fast stack
2
-
3
- Very efficient collection of ruby backtraces, even under heavy CPU load
4
-
5
- ### How do you use it?
6
-
7
- require 'fast_stack'
8
-
9
- ### Usage
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
- ### Changelog
28
-
29
- 0.1.0 - 17-Sep - Bugfix - deep callstacks could lead to an infinite loop
30
-
31
- ### Notes
32
-
33
- This technique was conceived by https://github.com/tmm1 , big thank you.
34
-
35
- Ruby 2.0 uses #backtrace_locations, 1.9.3 uses #backtrace
36
-
37
- (gem template based on https://github.com/CodeMonkeySteve/fast_xor )
1
+ # Fast stack [![Build Status](https://travis-ci.org/SamSaffron/fast_stack.svg?branch=master)](https://travis-ci.org/SamSaffron/fast_stack)
2
+
3
+ Very efficient collection of ruby backtraces, even under heavy CPU load
4
+
5
+ ### How do you use it?
6
+
7
+ ```ruby
8
+ require 'fast_stack'
9
+ ```
10
+
11
+ ### Usage
12
+
13
+ ```ruby
14
+ def fib( n )
15
+ return n if ( 0..1 ).include? n
16
+ ( fib( n - 1 ) + fib( n - 2 ) )
17
+ end
18
+
19
+ stacks = FastStack.profile do
20
+ fib(30)
21
+ end
22
+
23
+ puts stacks.count # => 30
24
+ ```
25
+
26
+ ### Notes
27
+
28
+ This technique was conceived by https://github.com/tmm1 , big thank you.
29
+
30
+ Ruby 2.0 uses #backtrace_locations, 1.9.3 uses #backtrace
31
+
32
+ (gem template based on https://github.com/CodeMonkeySteve/fast_xor )
@@ -1,8 +1,13 @@
1
- require 'mkmf'
2
- require 'rbconfig'
3
- require 'fileutils'
4
-
5
- # work around ruby 2.0 p0 bug
6
- FileUtils.mkdir_p(File.expand_path('../../../lib/fast_stack',__FILE__))
7
-
8
- create_makefile('fast_stack/fast_stack')
1
+ require 'mkmf'
2
+ require 'rbconfig'
3
+ require 'fileutils'
4
+
5
+ # work around ruby 2.0 p0 bug
6
+ FileUtils.mkdir_p(File.expand_path('../../../lib/fast_stack',__FILE__))
7
+
8
+ have_func('backtrace_symbols_fd')
9
+ have_func('CreateTimerQueueTimer')
10
+ have_library('winmm', 'timeBeginPeriod')
11
+
12
+
13
+ create_makefile('fast_stack/fast_stack')
@@ -1,46 +1,12 @@
1
- #include <stdio.h>
2
- #include <sys/time.h>
3
- #include <ruby.h>
4
- #include <ruby/encoding.h>
5
-
6
- static VALUE
7
- rb_profile_start(VALUE module, VALUE usec)
8
- {
9
- struct itimerval timer;
10
- timer.it_interval.tv_sec = 0;
11
- timer.it_interval.tv_usec = (suseconds_t)NUM2LONG(usec);
12
- timer.it_value = timer.it_interval;
13
- setitimer(ITIMER_REAL, &timer, 0);
14
-
15
- return Qnil;
16
- }
17
-
18
- static VALUE
19
- rb_profile_stop(VALUE module)
20
- {
21
- struct itimerval timer;
22
- memset(&timer, 0, sizeof(timer));
23
- setitimer(ITIMER_REAL, &timer, 0);
24
-
25
- return Qnil;
26
- }
27
-
28
- static VALUE
29
- rb_profile_block(VALUE module, VALUE usec)
30
- {
31
- rb_need_block();
32
-
33
- rb_profile_start(module, usec);
34
- rb_yield(Qundef);
35
- rb_profile_stop(module);
36
-
37
- return Qnil;
38
- }
39
-
40
- void Init_fast_stack( void )
41
- {
42
- VALUE rb_mFastStack = rb_define_module("FastStack");
43
- rb_define_module_function(rb_mFastStack, "profile_block", rb_profile_block, 1);
44
- rb_define_module_function(rb_mFastStack, "stop", rb_profile_stop, 0);
45
- rb_define_module_function(rb_mFastStack, "start", rb_profile_start, 1);
46
- }
1
+ #include "fast_stack.h"
2
+
3
+ void Init_fast_stack( void )
4
+ {
5
+ VALUE rb_mFastStack = rb_define_module("FastStack");
6
+ rb_define_module_function(rb_mFastStack, "start", rb_profile_start, 1);
7
+ rb_define_module_function(rb_mFastStack, "stop", rb_profile_stop, 0);
8
+ rb_define_module_function(rb_mFastStack, "signal", rb_profile_signal, 0);
9
+
10
+ rb_define_module_function(rb_mFastStack, "start_native", rb_profile_start_native, 2);
11
+ rb_define_module_function(rb_mFastStack, "stop_native", rb_profile_stop_native, 0);
12
+ }
@@ -0,0 +1,13 @@
1
+ #ifndef FAST_STACK_H__
2
+ #define FAST_STACK_H__
3
+
4
+ #include <ruby.h>
5
+ #include <ruby/encoding.h>
6
+
7
+ VALUE rb_profile_start_native(VALUE module, VALUE usec, VALUE fd);
8
+ VALUE rb_profile_stop_native(VALUE module);
9
+ VALUE rb_profile_start(VALUE module, VALUE usec);
10
+ VALUE rb_profile_stop(VALUE module);
11
+ VALUE rb_profile_signal(VALUE module);
12
+
13
+ #endif
@@ -0,0 +1,87 @@
1
+ #ifdef HAVE_BACKTRACE_SYMBOLS_FD
2
+
3
+ #include <stdio.h>
4
+ #include <unistd.h>
5
+ #include <stdlib.h>
6
+ #include <sys/time.h>
7
+ #include <sys/types.h>
8
+ #include <signal.h>
9
+ #include <execinfo.h>
10
+
11
+ #include "fast_stack.h"
12
+
13
+ struct sigaction old_alrm;
14
+ int backtrace_fd;
15
+
16
+ static void alrm_handler(int signum)
17
+ {
18
+ static void *trace[2048];
19
+ int n = backtrace(trace, 2048);
20
+
21
+ if(n>2){
22
+ backtrace_symbols_fd(trace + sizeof(void*)*2 , n-2, backtrace_fd);
23
+ write(backtrace_fd, "__SEP__\n", 8);
24
+ }
25
+ }
26
+
27
+ VALUE rb_profile_start_native(VALUE module, VALUE usec, VALUE fd)
28
+ {
29
+ struct itimerval timer;
30
+ struct sigaction sa;
31
+
32
+ backtrace_fd = NUM2INT(fd);
33
+ sigaction(SIGALRM, NULL, &old_alrm);
34
+
35
+ memset(&sa, 0, sizeof(sa));
36
+ sa.sa_handler = alrm_handler;
37
+ sigemptyset(&sa.sa_mask);
38
+ sigaction(SIGALRM, &sa, NULL);
39
+
40
+ timer.it_interval.tv_sec = 0;
41
+ timer.it_interval.tv_usec = (suseconds_t)NUM2LONG(usec);
42
+ timer.it_value = timer.it_interval;
43
+ setitimer(ITIMER_REAL, &timer, 0);
44
+
45
+ return Qnil;
46
+ }
47
+
48
+
49
+ VALUE rb_profile_stop_native(VALUE module)
50
+ {
51
+ struct itimerval timer;
52
+
53
+ sigaction(SIGALRM, &old_alrm, NULL);
54
+
55
+ memset(&timer, 0, sizeof(timer));
56
+ setitimer(ITIMER_REAL, &timer, 0);
57
+
58
+ return Qnil;
59
+ }
60
+
61
+ VALUE rb_profile_start(VALUE module, VALUE usec)
62
+ {
63
+ struct itimerval timer;
64
+
65
+ timer.it_interval.tv_sec = 0;
66
+ timer.it_interval.tv_usec = (suseconds_t)NUM2LONG(usec);
67
+ timer.it_value = timer.it_interval;
68
+ setitimer(ITIMER_REAL, &timer, 0);
69
+
70
+ return Qnil;
71
+ }
72
+
73
+ VALUE rb_profile_stop(VALUE module)
74
+ {
75
+ struct itimerval timer;
76
+ memset(&timer, 0, sizeof(timer));
77
+ setitimer(ITIMER_REAL, &timer, 0);
78
+
79
+ return Qnil;
80
+ }
81
+
82
+ VALUE rb_profile_signal(VALUE module)
83
+ {
84
+ return rb_str_new_cstr("ALRM");
85
+ }
86
+
87
+ #endif // HAVE_BACKTRACE_SYMBOLS_FD
@@ -0,0 +1,58 @@
1
+ #ifdef HAVE_CREATETIMERQUEUETIMER
2
+
3
+ #include "fast_stack.h"
4
+
5
+ static VALUE handler_proc;
6
+ static HANDLE timer = NULL;
7
+
8
+ VALUE rb_profile_start_native(VALUE module, VALUE usec, VALUE fd)
9
+ {
10
+ rb_raise(rb_eNotImpError, "Not implemented on Windows");
11
+ return Qnil;
12
+ }
13
+
14
+ VALUE rb_profile_stop_native(VALUE module)
15
+ {
16
+ rb_raise(rb_eNotImpError, "Not implemented on Windows");
17
+ return Qnil;
18
+ }
19
+
20
+ static void CALLBACK timer_handler(void* handler, BOOLEAN from_timer)
21
+ {
22
+ raise(SIGINT);
23
+ }
24
+
25
+ VALUE rb_profile_start(VALUE module, VALUE usec)
26
+ {
27
+ DWORD interval;
28
+
29
+ interval = NUM2LONG(usec) / 1000; /* Windows resolution is in milliseconds */
30
+
31
+ timeBeginPeriod(1);
32
+ if (!CreateTimerQueueTimer(&timer, NULL, &timer_handler, (void*)handler_proc,
33
+ interval, interval, WT_EXECUTEDEFAULT))
34
+ {
35
+ rb_raise(rb_eRuntimeError, "Cannot start timer: %d", GetLastError());
36
+ }
37
+
38
+ return Qnil;
39
+ }
40
+
41
+ VALUE rb_profile_stop(VALUE module)
42
+ {
43
+ if (timer)
44
+ {
45
+ DeleteTimerQueueTimer(NULL, timer, NULL);
46
+ timer = NULL;
47
+ }
48
+ timeEndPeriod(1);
49
+
50
+ return Qnil;
51
+ }
52
+
53
+ VALUE rb_profile_signal(VALUE module)
54
+ {
55
+ return rb_str_new_cstr("INT");
56
+ }
57
+
58
+ #endif // HAVE_CREATETIMERQUEUETIMER
data/lib/fast_stack.rb CHANGED
@@ -1,26 +1,142 @@
1
- require 'fast_stack/fast_stack'
2
- module FastStack
3
- def self.profile(millisecs=1, &blk)
4
- stacks = []
5
- thread = Thread.current
6
- last_time = Time.new
7
-
8
- new_api = thread.respond_to?(:backtrace_locations)
9
-
10
- trap('ALRM') do
11
- FastStack.stop
12
- stack = (new_api ? thread.backtrace_locations : thread.backtrace)
13
- # I am not sure if this is ensured to run in the thread
14
- # though in my samples it always does
15
- if thread == Thread.current
16
- stack = stack[2..-1]
17
- end
18
- stacks << stack
19
- FastStack.start(millisecs * 1000)
20
- end
21
-
22
- profile_block(millisecs * 1000, &blk)
23
-
24
- stacks
25
- end
26
- end
1
+ require 'fast_stack/fast_stack'
2
+ require 'tempfile'
3
+ module FastStack
4
+
5
+ def self.profile(millisecs=1, mode=:ruby, &blk)
6
+
7
+ return profile_native(millisecs, &blk) if mode == :c
8
+
9
+ stacks = []
10
+ thread = Thread.current
11
+
12
+ new_api = thread.respond_to?(:backtrace_locations)
13
+
14
+ handler do
15
+ FastStack.stop
16
+ stack = (new_api ? thread.backtrace_locations : thread.backtrace)
17
+ # I am not sure if this is ensured to run in the thread
18
+ # though in my samples it always does
19
+ if thread == Thread.current
20
+ stack = stack[2..-1]
21
+ end
22
+ stacks << stack
23
+ FastStack.start(millisecs*1000)
24
+ end
25
+
26
+ begin
27
+ FastStack.start(millisecs*1000)
28
+ blk.call
29
+ ensure
30
+ FastStack.stop
31
+ end
32
+
33
+ stacks
34
+ end
35
+
36
+
37
+ private
38
+
39
+ def self.handler(&block)
40
+ trap(signal, &block)
41
+ end
42
+
43
+ def self.profile_native(millisecs)
44
+ temp = Tempfile.new('stacks')
45
+ stacks = nil
46
+
47
+ begin
48
+ FastStack.start_native(millisecs*1000, temp.fileno)
49
+ yield
50
+ ensure
51
+ FastStack.stop_native
52
+ end
53
+
54
+ temp.flush
55
+ temp.close
56
+ temp.open
57
+ stacks = []
58
+ stack = []
59
+ temp.each_line do |line|
60
+ if line.strip == "__SEP__"
61
+ stacks << stack
62
+ stack = []
63
+ else
64
+ stack << line.strip
65
+ end
66
+ end
67
+ temp.close
68
+ temp.unlink
69
+
70
+ resolve_frames!(stacks)
71
+ stacks
72
+ end
73
+
74
+ def self.resolve_frames!(stacks)
75
+ frames = {}
76
+ resolved = {}
77
+ stacks.each do |stack|
78
+ stack.map! do |frame|
79
+ frames[frame] ||= resolve_frame(frame,resolved)
80
+ end
81
+ end
82
+ end
83
+
84
+ def self.process_name
85
+ @name ||= File.readlink("/proc/#{Process.pid}/exe")
86
+ end
87
+
88
+ def self.pmap
89
+ @pmap ||= begin
90
+
91
+ result = []
92
+
93
+ unparsed = `pmap #{Process.pid} | awk '{ printf $1; for(i=4;i<=10;i++) printf " %s ",$i; print "" }'`.split("\n")
94
+ unparsed[1..-1].each do |line|
95
+ split = line.split(" ")
96
+ if split[0] != "total"
97
+ result << [split[0].hex, split[1..-1].join(" ").strip]
98
+ end
99
+ end
100
+
101
+ result
102
+ end
103
+ end
104
+
105
+ def self.parse_frame(frame)
106
+ matches = frame.match(/(.*)\((.*)\)\[(.*)\]/)
107
+ {exe: matches[1], local: matches[2], global: matches[3]}
108
+ rescue
109
+ {exe: "unknown", local: "0", global: "0"}
110
+ end
111
+
112
+ def self.global_to_local(global)
113
+ prev = 0
114
+ pmap.each do |location, e|
115
+ if location > global
116
+ return global - prev
117
+ end
118
+ prev = location
119
+ end
120
+
121
+ 0
122
+ end
123
+
124
+ def self.resolve_frame(frame,resolved)
125
+ resolved[frame] ||= begin
126
+
127
+ parsed = parse_frame(frame)
128
+
129
+ resolved_location = global_to_local(parsed[:global].hex)
130
+
131
+ info = `addr2line -f -C -e #{process_name} 0x#{resolved_location.to_s(16)}`.split("\n")
132
+ parsed[:fn] = info[0].strip
133
+ parsed[:file], parsed[:line] = info[1].strip.split(":")
134
+
135
+ file = parsed[:file] == "??" ? parsed[:exe] : parsed[:file]
136
+ fn = parsed[:fn] == "??" ? parsed[:local] : parsed[:fn]
137
+
138
+ "#{file}:#{parsed[:line]}:in `#{fn}'"
139
+ end
140
+ end
141
+
142
+ end
@@ -1,28 +1,40 @@
1
- require 'fast_stack'
2
-
3
-
4
- describe String do
5
- it "works" do
6
- s = FastStack.profile do
7
- t = Time.new
8
- while (Time.new - t) < 0.1 do
9
- "nothing"
10
- end
11
- end
12
-
13
- expect(s.count).to be > 2
14
- end
15
-
16
- def fib( n )
17
- return n if ( 0..1 ).include? n
18
- ( fib( n - 1 ) + fib( n - 2 ) )
19
- end
20
-
21
- it "fibos" do
22
- s = FastStack.profile do
23
- fib(30)
24
- end
25
-
26
- expect(s.count).to be > 10
27
- end
28
- end
1
+ require 'fast_stack'
2
+
3
+
4
+ RSpec.describe String do
5
+
6
+ it "works for c mode" do
7
+ s = FastStack.profile(1, :c) do
8
+ t = Time.new
9
+ while (Time.new - t) < 0.01 do
10
+ "nothing"
11
+ end
12
+ end
13
+
14
+ expect(s.count).to be > 2
15
+ end
16
+
17
+ it "works" do
18
+ s = FastStack.profile do
19
+ t = Time.new
20
+ while (Time.new - t) < 0.1 do
21
+ "nothing"
22
+ end
23
+ end
24
+
25
+ expect(s.count).to be > 2
26
+ end
27
+
28
+ def fib( n )
29
+ return n if ( 0..1 ).include? n
30
+ ( fib( n - 1 ) + fib( n - 2 ) )
31
+ end
32
+
33
+ it "fibos" do
34
+ s = FastStack.profile do
35
+ fib(30)
36
+ end
37
+
38
+ expect(s.count).to be > 10
39
+ end
40
+ end
metadata CHANGED
@@ -1,58 +1,58 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fast_stack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-17 00:00:00.000000000 Z
11
+ date: 2016-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
- type: :runtime
20
+ type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake-compiler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
- type: :runtime
34
+ type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- description: Fast method for collecting stack traces in Ruby 2.1
55
+ description: Fast method for collecting stack traces in Ruby 2.1+
56
56
  email: sam.saffron@gmail.com
57
57
  executables: []
58
58
  extensions:
@@ -61,9 +61,12 @@ extra_rdoc_files: []
61
61
  files:
62
62
  - MIT-LICENSE
63
63
  - README.md
64
- - lib/fast_stack.rb
65
- - ext/fast_stack/fast_stack.c
66
64
  - ext/fast_stack/extconf.rb
65
+ - ext/fast_stack/fast_stack.c
66
+ - ext/fast_stack/fast_stack.h
67
+ - ext/fast_stack/fast_stack_linux.c
68
+ - ext/fast_stack/fast_stack_windows.c
69
+ - lib/fast_stack.rb
67
70
  - spec/fast_stack_spec.rb
68
71
  homepage: https://github.com/SamSaffron/fast_stack
69
72
  licenses:
@@ -75,19 +78,19 @@ require_paths:
75
78
  - lib
76
79
  required_ruby_version: !ruby/object:Gem::Requirement
77
80
  requirements:
78
- - - '>='
81
+ - - ">="
79
82
  - !ruby/object:Gem::Version
80
83
  version: '0'
81
84
  required_rubygems_version: !ruby/object:Gem::Requirement
82
85
  requirements:
83
- - - '>='
86
+ - - ">="
84
87
  - !ruby/object:Gem::Version
85
88
  version: '0'
86
89
  requirements: []
87
90
  rubyforge_project:
88
- rubygems_version: 2.0.3
91
+ rubygems_version: 2.4.8
89
92
  signing_key:
90
93
  specification_version: 4
91
- summary: Fast method for collecting stack traces in Ruby 2.1
94
+ summary: Fast method for collecting stack traces in Ruby 2.1+
92
95
  test_files:
93
96
  - spec/fast_stack_spec.rb