pf2 0.1.0 → 0.3.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 (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -2
  3. data/Cargo.lock +650 -0
  4. data/Cargo.toml +3 -0
  5. data/README.md +110 -13
  6. data/Rakefile +8 -0
  7. data/crates/backtrace-sys2/.gitignore +1 -0
  8. data/crates/backtrace-sys2/Cargo.toml +9 -0
  9. data/crates/backtrace-sys2/build.rs +48 -0
  10. data/crates/backtrace-sys2/src/lib.rs +5 -0
  11. data/crates/backtrace-sys2/src/libbacktrace/.gitignore +15 -0
  12. data/crates/backtrace-sys2/src/libbacktrace/Isaac.Newton-Opticks.txt +9286 -0
  13. data/crates/backtrace-sys2/src/libbacktrace/LICENSE +29 -0
  14. data/crates/backtrace-sys2/src/libbacktrace/Makefile.am +623 -0
  15. data/crates/backtrace-sys2/src/libbacktrace/Makefile.in +2666 -0
  16. data/crates/backtrace-sys2/src/libbacktrace/README.md +36 -0
  17. data/crates/backtrace-sys2/src/libbacktrace/aclocal.m4 +864 -0
  18. data/crates/backtrace-sys2/src/libbacktrace/alloc.c +167 -0
  19. data/crates/backtrace-sys2/src/libbacktrace/allocfail.c +136 -0
  20. data/crates/backtrace-sys2/src/libbacktrace/allocfail.sh +104 -0
  21. data/crates/backtrace-sys2/src/libbacktrace/atomic.c +113 -0
  22. data/crates/backtrace-sys2/src/libbacktrace/backtrace-supported.h.in +66 -0
  23. data/crates/backtrace-sys2/src/libbacktrace/backtrace.c +129 -0
  24. data/crates/backtrace-sys2/src/libbacktrace/backtrace.h +189 -0
  25. data/crates/backtrace-sys2/src/libbacktrace/btest.c +501 -0
  26. data/crates/backtrace-sys2/src/libbacktrace/compile +348 -0
  27. data/crates/backtrace-sys2/src/libbacktrace/config/enable.m4 +38 -0
  28. data/crates/backtrace-sys2/src/libbacktrace/config/lead-dot.m4 +31 -0
  29. data/crates/backtrace-sys2/src/libbacktrace/config/libtool.m4 +7436 -0
  30. data/crates/backtrace-sys2/src/libbacktrace/config/ltoptions.m4 +369 -0
  31. data/crates/backtrace-sys2/src/libbacktrace/config/ltsugar.m4 +123 -0
  32. data/crates/backtrace-sys2/src/libbacktrace/config/ltversion.m4 +23 -0
  33. data/crates/backtrace-sys2/src/libbacktrace/config/lt~obsolete.m4 +98 -0
  34. data/crates/backtrace-sys2/src/libbacktrace/config/multi.m4 +68 -0
  35. data/crates/backtrace-sys2/src/libbacktrace/config/override.m4 +117 -0
  36. data/crates/backtrace-sys2/src/libbacktrace/config/unwind_ipinfo.m4 +37 -0
  37. data/crates/backtrace-sys2/src/libbacktrace/config/warnings.m4 +227 -0
  38. data/crates/backtrace-sys2/src/libbacktrace/config.guess +1700 -0
  39. data/crates/backtrace-sys2/src/libbacktrace/config.h.in +182 -0
  40. data/crates/backtrace-sys2/src/libbacktrace/config.sub +1885 -0
  41. data/crates/backtrace-sys2/src/libbacktrace/configure +15740 -0
  42. data/crates/backtrace-sys2/src/libbacktrace/configure.ac +613 -0
  43. data/crates/backtrace-sys2/src/libbacktrace/dwarf.c +4402 -0
  44. data/crates/backtrace-sys2/src/libbacktrace/edtest.c +120 -0
  45. data/crates/backtrace-sys2/src/libbacktrace/edtest2.c +43 -0
  46. data/crates/backtrace-sys2/src/libbacktrace/elf.c +7443 -0
  47. data/crates/backtrace-sys2/src/libbacktrace/fileline.c +407 -0
  48. data/crates/backtrace-sys2/src/libbacktrace/filenames.h +52 -0
  49. data/crates/backtrace-sys2/src/libbacktrace/filetype.awk +13 -0
  50. data/crates/backtrace-sys2/src/libbacktrace/install-debuginfo-for-buildid.sh.in +65 -0
  51. data/crates/backtrace-sys2/src/libbacktrace/install-sh +501 -0
  52. data/crates/backtrace-sys2/src/libbacktrace/instrumented_alloc.c +114 -0
  53. data/crates/backtrace-sys2/src/libbacktrace/internal.h +389 -0
  54. data/crates/backtrace-sys2/src/libbacktrace/libtool.m4 +7436 -0
  55. data/crates/backtrace-sys2/src/libbacktrace/ltmain.sh +8636 -0
  56. data/crates/backtrace-sys2/src/libbacktrace/ltoptions.m4 +369 -0
  57. data/crates/backtrace-sys2/src/libbacktrace/ltsugar.m4 +123 -0
  58. data/crates/backtrace-sys2/src/libbacktrace/ltversion.m4 +23 -0
  59. data/crates/backtrace-sys2/src/libbacktrace/lt~obsolete.m4 +98 -0
  60. data/crates/backtrace-sys2/src/libbacktrace/macho.c +1355 -0
  61. data/crates/backtrace-sys2/src/libbacktrace/missing +215 -0
  62. data/crates/backtrace-sys2/src/libbacktrace/mmap.c +331 -0
  63. data/crates/backtrace-sys2/src/libbacktrace/mmapio.c +110 -0
  64. data/crates/backtrace-sys2/src/libbacktrace/move-if-change +83 -0
  65. data/crates/backtrace-sys2/src/libbacktrace/mtest.c +410 -0
  66. data/crates/backtrace-sys2/src/libbacktrace/nounwind.c +66 -0
  67. data/crates/backtrace-sys2/src/libbacktrace/pecoff.c +957 -0
  68. data/crates/backtrace-sys2/src/libbacktrace/posix.c +104 -0
  69. data/crates/backtrace-sys2/src/libbacktrace/print.c +92 -0
  70. data/crates/backtrace-sys2/src/libbacktrace/read.c +110 -0
  71. data/crates/backtrace-sys2/src/libbacktrace/simple.c +108 -0
  72. data/crates/backtrace-sys2/src/libbacktrace/sort.c +108 -0
  73. data/crates/backtrace-sys2/src/libbacktrace/state.c +72 -0
  74. data/crates/backtrace-sys2/src/libbacktrace/stest.c +137 -0
  75. data/crates/backtrace-sys2/src/libbacktrace/test-driver +148 -0
  76. data/crates/backtrace-sys2/src/libbacktrace/test_format.c +55 -0
  77. data/crates/backtrace-sys2/src/libbacktrace/testlib.c +234 -0
  78. data/crates/backtrace-sys2/src/libbacktrace/testlib.h +110 -0
  79. data/crates/backtrace-sys2/src/libbacktrace/ttest.c +161 -0
  80. data/crates/backtrace-sys2/src/libbacktrace/unittest.c +92 -0
  81. data/crates/backtrace-sys2/src/libbacktrace/unknown.c +65 -0
  82. data/crates/backtrace-sys2/src/libbacktrace/xcoff.c +1606 -0
  83. data/crates/backtrace-sys2/src/libbacktrace/xztest.c +508 -0
  84. data/crates/backtrace-sys2/src/libbacktrace/zstdtest.c +523 -0
  85. data/crates/backtrace-sys2/src/libbacktrace/ztest.c +541 -0
  86. data/ext/pf2/Cargo.toml +25 -0
  87. data/ext/pf2/build.rs +3 -0
  88. data/ext/pf2/extconf.rb +6 -1
  89. data/ext/pf2/src/backtrace.rs +126 -0
  90. data/ext/pf2/src/lib.rs +15 -0
  91. data/ext/pf2/src/profile.rs +65 -0
  92. data/ext/pf2/src/profile_serializer.rs +204 -0
  93. data/ext/pf2/src/ringbuffer.rs +152 -0
  94. data/ext/pf2/src/ruby_init.rs +74 -0
  95. data/ext/pf2/src/sample.rs +66 -0
  96. data/ext/pf2/src/siginfo_t.c +5 -0
  97. data/ext/pf2/src/signal_scheduler/configuration.rs +31 -0
  98. data/ext/pf2/src/signal_scheduler/timer_installer.rs +199 -0
  99. data/ext/pf2/src/signal_scheduler.rs +311 -0
  100. data/ext/pf2/src/timer_thread_scheduler.rs +319 -0
  101. data/ext/pf2/src/util.rs +30 -0
  102. data/lib/pf2/cli.rb +1 -1
  103. data/lib/pf2/reporter.rb +48 -16
  104. data/lib/pf2/version.rb +1 -1
  105. data/lib/pf2.rb +20 -5
  106. metadata +128 -5
  107. data/ext/pf2/pf2.c +0 -246
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pf2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daisuke Aritomo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-04 00:00:00.000000000 Z
11
+ date: 2024-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rb_sys
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.9.63
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.9.63
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
27
55
  description:
28
56
  email:
29
57
  - osyoyu@osyoyu.com
@@ -34,12 +62,107 @@ extensions:
34
62
  extra_rdoc_files: []
35
63
  files:
36
64
  - CHANGELOG.md
65
+ - Cargo.lock
66
+ - Cargo.toml
37
67
  - LICENSE.txt
38
68
  - README.md
39
69
  - Rakefile
70
+ - crates/backtrace-sys2/.gitignore
71
+ - crates/backtrace-sys2/Cargo.toml
72
+ - crates/backtrace-sys2/build.rs
73
+ - crates/backtrace-sys2/src/lib.rs
74
+ - crates/backtrace-sys2/src/libbacktrace/.gitignore
75
+ - crates/backtrace-sys2/src/libbacktrace/Isaac.Newton-Opticks.txt
76
+ - crates/backtrace-sys2/src/libbacktrace/LICENSE
77
+ - crates/backtrace-sys2/src/libbacktrace/Makefile.am
78
+ - crates/backtrace-sys2/src/libbacktrace/Makefile.in
79
+ - crates/backtrace-sys2/src/libbacktrace/README.md
80
+ - crates/backtrace-sys2/src/libbacktrace/aclocal.m4
81
+ - crates/backtrace-sys2/src/libbacktrace/alloc.c
82
+ - crates/backtrace-sys2/src/libbacktrace/allocfail.c
83
+ - crates/backtrace-sys2/src/libbacktrace/allocfail.sh
84
+ - crates/backtrace-sys2/src/libbacktrace/atomic.c
85
+ - crates/backtrace-sys2/src/libbacktrace/backtrace-supported.h.in
86
+ - crates/backtrace-sys2/src/libbacktrace/backtrace.c
87
+ - crates/backtrace-sys2/src/libbacktrace/backtrace.h
88
+ - crates/backtrace-sys2/src/libbacktrace/btest.c
89
+ - crates/backtrace-sys2/src/libbacktrace/compile
90
+ - crates/backtrace-sys2/src/libbacktrace/config.guess
91
+ - crates/backtrace-sys2/src/libbacktrace/config.h.in
92
+ - crates/backtrace-sys2/src/libbacktrace/config.sub
93
+ - crates/backtrace-sys2/src/libbacktrace/config/enable.m4
94
+ - crates/backtrace-sys2/src/libbacktrace/config/lead-dot.m4
95
+ - crates/backtrace-sys2/src/libbacktrace/config/libtool.m4
96
+ - crates/backtrace-sys2/src/libbacktrace/config/ltoptions.m4
97
+ - crates/backtrace-sys2/src/libbacktrace/config/ltsugar.m4
98
+ - crates/backtrace-sys2/src/libbacktrace/config/ltversion.m4
99
+ - crates/backtrace-sys2/src/libbacktrace/config/lt~obsolete.m4
100
+ - crates/backtrace-sys2/src/libbacktrace/config/multi.m4
101
+ - crates/backtrace-sys2/src/libbacktrace/config/override.m4
102
+ - crates/backtrace-sys2/src/libbacktrace/config/unwind_ipinfo.m4
103
+ - crates/backtrace-sys2/src/libbacktrace/config/warnings.m4
104
+ - crates/backtrace-sys2/src/libbacktrace/configure
105
+ - crates/backtrace-sys2/src/libbacktrace/configure.ac
106
+ - crates/backtrace-sys2/src/libbacktrace/dwarf.c
107
+ - crates/backtrace-sys2/src/libbacktrace/edtest.c
108
+ - crates/backtrace-sys2/src/libbacktrace/edtest2.c
109
+ - crates/backtrace-sys2/src/libbacktrace/elf.c
110
+ - crates/backtrace-sys2/src/libbacktrace/fileline.c
111
+ - crates/backtrace-sys2/src/libbacktrace/filenames.h
112
+ - crates/backtrace-sys2/src/libbacktrace/filetype.awk
113
+ - crates/backtrace-sys2/src/libbacktrace/install-debuginfo-for-buildid.sh.in
114
+ - crates/backtrace-sys2/src/libbacktrace/install-sh
115
+ - crates/backtrace-sys2/src/libbacktrace/instrumented_alloc.c
116
+ - crates/backtrace-sys2/src/libbacktrace/internal.h
117
+ - crates/backtrace-sys2/src/libbacktrace/libtool.m4
118
+ - crates/backtrace-sys2/src/libbacktrace/ltmain.sh
119
+ - crates/backtrace-sys2/src/libbacktrace/ltoptions.m4
120
+ - crates/backtrace-sys2/src/libbacktrace/ltsugar.m4
121
+ - crates/backtrace-sys2/src/libbacktrace/ltversion.m4
122
+ - crates/backtrace-sys2/src/libbacktrace/lt~obsolete.m4
123
+ - crates/backtrace-sys2/src/libbacktrace/macho.c
124
+ - crates/backtrace-sys2/src/libbacktrace/missing
125
+ - crates/backtrace-sys2/src/libbacktrace/mmap.c
126
+ - crates/backtrace-sys2/src/libbacktrace/mmapio.c
127
+ - crates/backtrace-sys2/src/libbacktrace/move-if-change
128
+ - crates/backtrace-sys2/src/libbacktrace/mtest.c
129
+ - crates/backtrace-sys2/src/libbacktrace/nounwind.c
130
+ - crates/backtrace-sys2/src/libbacktrace/pecoff.c
131
+ - crates/backtrace-sys2/src/libbacktrace/posix.c
132
+ - crates/backtrace-sys2/src/libbacktrace/print.c
133
+ - crates/backtrace-sys2/src/libbacktrace/read.c
134
+ - crates/backtrace-sys2/src/libbacktrace/simple.c
135
+ - crates/backtrace-sys2/src/libbacktrace/sort.c
136
+ - crates/backtrace-sys2/src/libbacktrace/state.c
137
+ - crates/backtrace-sys2/src/libbacktrace/stest.c
138
+ - crates/backtrace-sys2/src/libbacktrace/test-driver
139
+ - crates/backtrace-sys2/src/libbacktrace/test_format.c
140
+ - crates/backtrace-sys2/src/libbacktrace/testlib.c
141
+ - crates/backtrace-sys2/src/libbacktrace/testlib.h
142
+ - crates/backtrace-sys2/src/libbacktrace/ttest.c
143
+ - crates/backtrace-sys2/src/libbacktrace/unittest.c
144
+ - crates/backtrace-sys2/src/libbacktrace/unknown.c
145
+ - crates/backtrace-sys2/src/libbacktrace/xcoff.c
146
+ - crates/backtrace-sys2/src/libbacktrace/xztest.c
147
+ - crates/backtrace-sys2/src/libbacktrace/zstdtest.c
148
+ - crates/backtrace-sys2/src/libbacktrace/ztest.c
40
149
  - exe/pf2
150
+ - ext/pf2/Cargo.toml
151
+ - ext/pf2/build.rs
41
152
  - ext/pf2/extconf.rb
42
- - ext/pf2/pf2.c
153
+ - ext/pf2/src/backtrace.rs
154
+ - ext/pf2/src/lib.rs
155
+ - ext/pf2/src/profile.rs
156
+ - ext/pf2/src/profile_serializer.rs
157
+ - ext/pf2/src/ringbuffer.rs
158
+ - ext/pf2/src/ruby_init.rs
159
+ - ext/pf2/src/sample.rs
160
+ - ext/pf2/src/siginfo_t.c
161
+ - ext/pf2/src/signal_scheduler.rs
162
+ - ext/pf2/src/signal_scheduler/configuration.rs
163
+ - ext/pf2/src/signal_scheduler/timer_installer.rs
164
+ - ext/pf2/src/timer_thread_scheduler.rs
165
+ - ext/pf2/src/util.rs
43
166
  - lib/pf2.rb
44
167
  - lib/pf2/cli.rb
45
168
  - lib/pf2/reporter.rb
@@ -60,14 +183,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
60
183
  requirements:
61
184
  - - ">="
62
185
  - !ruby/object:Gem::Version
63
- version: 3.3.0.dev
186
+ version: 3.3.0
64
187
  required_rubygems_version: !ruby/object:Gem::Requirement
65
188
  requirements:
66
189
  - - ">="
67
190
  - !ruby/object:Gem::Version
68
191
  version: '0'
69
192
  requirements: []
70
- rubygems_version: 3.5.0.dev
193
+ rubygems_version: 3.6.0.dev
71
194
  signing_key:
72
195
  specification_version: 4
73
196
  summary: Yet another Ruby profiler
data/ext/pf2/pf2.c DELETED
@@ -1,246 +0,0 @@
1
- #include <errno.h>
2
- #include <signal.h>
3
- #include <stdbool.h>
4
- #include <stdio.h>
5
- #include <stdlib.h>
6
- #include <unistd.h>
7
-
8
- #include <ruby.h>
9
- #include <ruby/debug.h>
10
- #include <ruby/thread.h>
11
-
12
- #define MAX_BUFFER_SIZE 3000
13
-
14
- struct pf2_buffer_t {
15
- VALUE framebuffer[MAX_BUFFER_SIZE];
16
- int linebuffer[MAX_BUFFER_SIZE];
17
- };
18
-
19
- // Ruby functions
20
- void Init_pf2(void);
21
- VALUE rb_start(VALUE self, VALUE debug);
22
- VALUE rb_stop(VALUE self);
23
-
24
- static void pf2_start(void);
25
- static void pf2_stop(void);
26
- static void pf2_signal_handler(int signo);
27
- static void pf2_postponed_job(void *_);
28
-
29
- static void pf2_record(struct pf2_buffer_t *buffer);
30
- static VALUE find_or_create_thread_results(VALUE results, pid_t thread_id);
31
-
32
- // Buffer to record rb_profile_frames() results
33
- struct pf2_buffer_t buffer;
34
- // The time when the profiler started
35
- struct timespec initial_time;
36
- // Debug print?
37
- bool _debug = false;
38
-
39
- void
40
- Init_pf2(void)
41
- {
42
- VALUE rb_mPf2 = rb_define_module("Pf2");
43
- rb_define_module_function(rb_mPf2, "start", rb_start, 1);
44
- rb_define_module_function(rb_mPf2, "stop", rb_stop, 0);
45
- }
46
-
47
- VALUE
48
- rb_start(VALUE self, VALUE debug) {
49
- _debug = RTEST(debug);
50
-
51
- /**
52
- * {
53
- * sequence: 0,
54
- * threads: {},
55
- * }
56
- */
57
- VALUE results = rb_hash_new();
58
- rb_hash_aset(results, ID2SYM(rb_intern_const("sequence")), INT2FIX(0));
59
- rb_hash_aset(results, ID2SYM(rb_intern_const("threads")), rb_hash_new());
60
-
61
- rb_iv_set(self, "@results", results);
62
-
63
- pf2_start();
64
-
65
- if (_debug) {
66
- rb_funcall(rb_mKernel, rb_intern("puts"), 1, rb_str_new_cstr("[debug] Pf2 started"));
67
- }
68
-
69
- return results;
70
- }
71
-
72
- VALUE
73
- rb_stop(VALUE self) {
74
- pf2_stop();
75
-
76
- if (_debug) {
77
- rb_funcall(rb_mKernel, rb_intern("puts"), 1, rb_str_new_cstr("[debug] Pf2 stopped"));
78
- }
79
-
80
- return rb_iv_get(self, "@results");
81
- }
82
-
83
- static void
84
- pf2_start(void)
85
- {
86
- clock_gettime(CLOCK_MONOTONIC, &initial_time);
87
-
88
- // Configure timer for every 10 ms
89
- // TODO: Make interval configurable
90
- struct itimerval timer;
91
- timer.it_value.tv_sec = 1;
92
- timer.it_value.tv_usec = 0;
93
- timer.it_interval.tv_sec = 0;
94
- timer.it_interval.tv_usec = 10 * 1000; // 10 ms
95
- if (signal(SIGALRM, pf2_signal_handler) == SIG_ERR) {
96
- rb_syserr_fail(errno, "Failed to configure profiling timer");
97
- };
98
- if (setitimer(ITIMER_REAL, &timer, NULL) == -1) {
99
- rb_syserr_fail(errno, "Failed to configure profiling timer");
100
- };
101
- }
102
-
103
- static void
104
- pf2_stop(void)
105
- {
106
- struct itimerval timer = { 0 }; // stop
107
- setitimer(ITIMER_REAL, &timer, NULL);
108
- }
109
-
110
- // async-signal-safe
111
- static void
112
- pf2_signal_handler(int signo)
113
- {
114
- rb_postponed_job_register_one(0, pf2_postponed_job, 0);
115
- }
116
-
117
- static void
118
- pf2_postponed_job(void *_) {
119
- pf2_record(&buffer);
120
- };
121
-
122
- // Buffer structure
123
- static void
124
- pf2_record(struct pf2_buffer_t *buffer)
125
- {
126
- // get the current time
127
- struct timespec ts;
128
- clock_gettime(CLOCK_MONOTONIC, &ts);
129
-
130
- VALUE rb_mPf2 = rb_const_get(rb_cObject, rb_intern("Pf2"));
131
- VALUE results = rb_iv_get(rb_mPf2, "@results");
132
-
133
- // Iterate over all Threads
134
- VALUE threads = rb_iv_get(rb_mPf2, "@@threads");
135
- for (int i = 0; i < RARRAY_LEN(threads); i++) {
136
- VALUE thread = rb_ary_entry(threads, i);
137
- VALUE thread_status = rb_funcall(thread, rb_intern("status"), 0);
138
- if (NIL_P(thread) || thread_status == Qfalse) {
139
- // Thread is dead, just ignore
140
- continue;
141
- }
142
-
143
- pid_t thread_id = NUM2INT(rb_funcall(thread, rb_intern("native_thread_id"), 0));
144
- VALUE thread_results = find_or_create_thread_results(results, thread_id);
145
- assert(!NIL_P(thread_results));
146
-
147
- // The actual querying
148
- int stack_depth = rb_profile_thread_frames(thread, 0, MAX_BUFFER_SIZE, buffer->framebuffer, buffer->linebuffer);
149
-
150
- // TODO: Reimplement Pf2-internal data structures without CRuby
151
- // (which will allow us to release the GVL at this point)
152
- // rb_thread_call_without_gvl(...);
153
-
154
- VALUE frames_table = rb_hash_lookup(thread_results, ID2SYM(rb_intern_const("frames")));
155
- assert(!NIL_P(frames_table));
156
- VALUE samples = rb_hash_lookup(thread_results, ID2SYM(rb_intern_const("samples")));
157
- assert(!NIL_P(samples));
158
-
159
- // Dig down the stack (top of call stack -> bottom (root))
160
- VALUE stack_tree_p = rb_hash_lookup(thread_results, ID2SYM(rb_intern_const("stack_tree")));
161
- for (int i = stack_depth - 1; i >= 0; i--) {
162
- assert(NIL_P(buffer->framebuffer[i]));
163
-
164
- // Collect & record frame information
165
- VALUE frame_obj_id = rb_obj_id(buffer->framebuffer[i]);
166
- VALUE frame_table_entry = rb_hash_aref(frames_table, frame_obj_id);
167
- if (NIL_P(frame_table_entry)) {
168
- frame_table_entry = rb_hash_new();
169
- rb_hash_aset(frame_table_entry, ID2SYM(rb_intern_const("full_label")), rb_profile_frame_full_label(buffer->framebuffer[i]));
170
- rb_hash_aset(frames_table, frame_obj_id, frame_table_entry);
171
- }
172
-
173
- VALUE children = rb_hash_aref(stack_tree_p, ID2SYM(rb_intern_const("children")));
174
- VALUE next_node = rb_hash_lookup(children, frame_obj_id);
175
- // If this is the first time we see this frame, register it to the stack tree
176
- if (NIL_P(next_node)) { // not found
177
- next_node = rb_hash_new();
178
-
179
- // Increment sequence
180
- VALUE next =
181
- rb_funcall(
182
- rb_hash_lookup(results, ID2SYM(rb_intern_const("sequence"))),
183
- rb_intern("+"),
184
- 1,
185
- INT2FIX(1)
186
- );
187
- rb_hash_aset(results, ID2SYM(rb_intern_const("sequence")), next);
188
-
189
- rb_hash_aset(next_node, ID2SYM(rb_intern_const("node_id")), INT2FIX(next));
190
- rb_hash_aset(next_node, ID2SYM(rb_intern_const("frame_id")), frame_obj_id);
191
- rb_hash_aset(next_node, ID2SYM(rb_intern_const("full_label")), rb_profile_frame_full_label(buffer->framebuffer[i]));
192
- rb_hash_aset(next_node, ID2SYM(rb_intern_const("children")), rb_hash_new());
193
-
194
- rb_hash_aset(children, frame_obj_id, next_node);
195
- }
196
-
197
- VALUE stack_tree_id = rb_hash_aref(next_node, ID2SYM(rb_intern_const("node_id")));
198
-
199
- // If on leaf
200
- if (i == 0) {
201
- // Record sample
202
- VALUE sample = rb_hash_new();
203
- rb_hash_aset(sample, ID2SYM(rb_intern_const("stack_tree_id")), stack_tree_id);
204
- unsigned long long nsec = (ts.tv_sec - initial_time.tv_sec) * 1000000000 + ts.tv_nsec - initial_time.tv_nsec;
205
- rb_hash_aset(sample, ID2SYM(rb_intern_const("timestamp")), ULL2NUM(nsec));
206
- rb_ary_push(samples, sample);
207
- }
208
-
209
- stack_tree_p = next_node;
210
- }
211
- }
212
- }
213
-
214
- static VALUE
215
- find_or_create_thread_results(VALUE results, pid_t thread_id) {
216
- assert(!NIL_P(results));
217
- assert(!NIL_P(thread));
218
-
219
- VALUE threads = rb_hash_aref(results, ID2SYM(rb_intern_const("threads")));
220
- VALUE thread_results = rb_hash_aref(threads, INT2NUM(thread_id));
221
- if (NIL_P(thread_results)) {
222
- /**
223
- * {
224
- * thread_id: 1,
225
- * frames: [],
226
- * stack_tree: {
227
- * node_id: ...,
228
- * children: {}
229
- * },
230
- * samples: [],
231
- * }
232
- */
233
- thread_results = rb_hash_new();
234
- rb_hash_aset(thread_results, ID2SYM(rb_intern_const("thread_id")), INT2NUM(thread_id));
235
-
236
- rb_hash_aset(thread_results, ID2SYM(rb_intern_const("frames")), rb_hash_new());
237
- VALUE stack_tree = rb_hash_aset(thread_results, ID2SYM(rb_intern_const("stack_tree")), rb_hash_new());
238
- rb_hash_aset(stack_tree, ID2SYM(rb_intern_const("node_id")), ID2SYM(rb_intern_const("root")));
239
- rb_hash_aset(stack_tree, ID2SYM(rb_intern_const("children")), rb_hash_new());
240
- rb_hash_aset(thread_results, ID2SYM(rb_intern_const("samples")), rb_ary_new());
241
- rb_hash_aset(thread_results, ID2SYM(rb_intern_const("gvl_timings")), rb_ary_new());
242
-
243
- rb_hash_aset(threads, INT2NUM(thread_id), thread_results);
244
- }
245
- return thread_results;
246
- }