gvl-tracing 1.5.2 → 1.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.adoc +7 -1
- data/ext/gvl_tracing_native_extension/gvl_tracing.c +112 -28
- data/gvl-tracing.gemspec +2 -1
- data/lib/gvl-tracing.rb +2 -2
- data/lib/gvl_tracing/sleep_tracking.rb +1 -1
- data/lib/gvl_tracing/version.rb +1 -1
- data/preview.png +0 -0
- metadata +3 -8
- data/.editorconfig +0 -22
- data/.ruby-version +0 -1
- data/.standard.yml +0 -9
- data/Rakefile +0 -36
- data/gems.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2bf28c6665bf4afa02c13299947bb65d7c62c3af783858afdc3a5383e334fa47
|
4
|
+
data.tar.gz: b1999e7e17d56e76ba732962708c14979e2690cd78204946d2f05e7146b05725
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: feb5fb173e07343af18c929608b20b2463fc0b676565b926242585f3fed31991e34ab5f549d7cbfe0e26c883d4a1e6eebf1d8da9e1586f0fa63d0890cdd3b108
|
7
|
+
data.tar.gz: 615226e345e230b989d7738754f02a058935d67679b4ca16c610cbbb6fe34f82aff6de3299d9548af579a30d55bccaedf25cd52d4f631023cff93a683fe3c8bb
|
data/README.adoc
CHANGED
@@ -25,7 +25,7 @@ def fib(n)
|
|
25
25
|
fib(n - 1) + fib(n - 2)
|
26
26
|
end
|
27
27
|
|
28
|
-
GvlTracing.start("example1.json") do
|
28
|
+
GvlTracing.start("example1.json", os_threads_view_enabled: false) do
|
29
29
|
Thread.new { sleep(0.05) while true }
|
30
30
|
|
31
31
|
sleep(0.05)
|
@@ -68,6 +68,12 @@ This gem only provides a single module (`GvlTracing`) with methods:
|
|
68
68
|
|
69
69
|
The resulting traces can be analyzed by going to https://ui.perfetto.dev/[Perfetto UI].
|
70
70
|
|
71
|
+
== Experimental features
|
72
|
+
|
73
|
+
1. Sleep tracking: Add `require 'gvl_tracing/sleep_tracking'` to add a more specific `sleeping` state for sleeps (which are otherwise rendered as `waiting` without this feature)
|
74
|
+
|
75
|
+
2. OS threads view: Pass in `os_threads_view_enabled: true` to `GvlTracing.start` to also render a view of Ruby thread activity from the OS native threads point-of-view. This is useful when using M:N thread scheduling, which is used on Ruby 3.3+ Ractors, and when using the `RUBY_MN_THREADS=1` setting.
|
76
|
+
|
71
77
|
== Tips
|
72
78
|
|
73
79
|
You can "embed" links to the perfetto UI which trigger loading of a trace by following the instructions on https://perfetto.dev/docs/visualization/deep-linking-to-perfetto-ui .
|
@@ -32,6 +32,7 @@
|
|
32
32
|
#include <stdbool.h>
|
33
33
|
#include <sys/types.h>
|
34
34
|
#include <pthread.h>
|
35
|
+
#include <stdint.h>
|
35
36
|
|
36
37
|
#include "extconf.h"
|
37
38
|
|
@@ -56,6 +57,10 @@
|
|
56
57
|
#define RUBY_3_2
|
57
58
|
#endif
|
58
59
|
|
60
|
+
// For the OS threads view, we emit data as if it was for another pid so it gets grouped separately in perfetto.
|
61
|
+
// This is a really big hack, but I couldn't think of a better way?
|
62
|
+
#define OS_THREADS_VIEW_PID (INT64_C(0))
|
63
|
+
|
59
64
|
typedef struct {
|
60
65
|
bool initialized;
|
61
66
|
int32_t current_thread_serial;
|
@@ -78,20 +83,27 @@ static VALUE gc_tracepoint = Qnil;
|
|
78
83
|
static int thread_storage_key = 0;
|
79
84
|
static VALUE all_seen_threads = Qnil;
|
80
85
|
static pthread_mutex_t all_seen_threads_mutex = PTHREAD_MUTEX_INITIALIZER;
|
86
|
+
static pthread_mutex_t output_mutex = PTHREAD_MUTEX_INITIALIZER;
|
87
|
+
static bool os_threads_view_enabled;
|
81
88
|
|
82
89
|
static VALUE tracing_init_local_storage(VALUE, VALUE);
|
83
|
-
static VALUE tracing_start(VALUE _self, VALUE output_path);
|
90
|
+
static VALUE tracing_start(UNUSED_ARG VALUE _self, VALUE output_path, VALUE os_threads_view_enabled_arg);
|
84
91
|
static VALUE tracing_stop(VALUE _self);
|
85
92
|
static double timestamp_microseconds(void);
|
86
|
-
static
|
93
|
+
static double render_event(thread_local_state *, const char *event_name);
|
87
94
|
static void on_thread_event(rb_event_flag_t event, const rb_internal_thread_event_data_t *_unused1, void *_unused2);
|
88
95
|
static void on_gc_event(VALUE tpval, void *_unused1);
|
89
96
|
static VALUE mark_sleeping(VALUE _self);
|
90
97
|
static size_t thread_local_state_memsize(UNUSED_ARG const void *_unused);
|
91
98
|
static void thread_local_state_mark(void *data);
|
99
|
+
static inline void output_mutex_lock(void);
|
100
|
+
static inline void output_mutex_unlock(void);
|
92
101
|
static inline int32_t thread_id_for(thread_local_state *state);
|
93
102
|
static VALUE ruby_thread_id_for(UNUSED_ARG VALUE _self, VALUE thread);
|
94
103
|
static VALUE trim_all_seen_threads(UNUSED_ARG VALUE _self);
|
104
|
+
static void render_os_thread_event(thread_local_state *state, double now_microseconds);
|
105
|
+
static void finish_previous_os_thread_event(double now_microseconds);
|
106
|
+
static inline uint32_t current_native_thread_id(void);
|
95
107
|
|
96
108
|
#pragma GCC diagnostic ignored "-Wunused-const-variable"
|
97
109
|
static const rb_data_type_t thread_local_state_type = {
|
@@ -131,7 +143,7 @@ void Init_gvl_tracing_native_extension(void) {
|
|
131
143
|
VALUE gvl_tracing_module = rb_define_module("GvlTracing");
|
132
144
|
|
133
145
|
rb_define_singleton_method(gvl_tracing_module, "_init_local_storage", tracing_init_local_storage, 1);
|
134
|
-
rb_define_singleton_method(gvl_tracing_module, "_start", tracing_start,
|
146
|
+
rb_define_singleton_method(gvl_tracing_module, "_start", tracing_start, 2);
|
135
147
|
rb_define_singleton_method(gvl_tracing_module, "_stop", tracing_stop, 0);
|
136
148
|
rb_define_singleton_method(gvl_tracing_module, "mark_sleeping", mark_sleeping, 0);
|
137
149
|
rb_define_singleton_method(gvl_tracing_module, "_thread_id_for", ruby_thread_id_for, 1);
|
@@ -143,24 +155,7 @@ static inline void initialize_thread_local_state(thread_local_state *state) {
|
|
143
155
|
state->current_thread_serial = RUBY_ATOMIC_FETCH_ADD(thread_serial, 1);
|
144
156
|
|
145
157
|
#ifdef RUBY_3_2
|
146
|
-
|
147
|
-
|
148
|
-
#ifdef HAVE_PTHREAD_THREADID_NP
|
149
|
-
uint64_t full_native_thread_id;
|
150
|
-
pthread_threadid_np(pthread_self(), &full_native_thread_id);
|
151
|
-
// Note: `pthread_threadid_np` is declared as taking in a `uint64_t` but I don't think macOS uses such really
|
152
|
-
// high thread ids, and anyway perfetto doesn't like full 64-bit ids for threads so let's go with a simplification
|
153
|
-
// for now.
|
154
|
-
native_thread_id = (uint32_t) full_native_thread_id;
|
155
|
-
#elif HAVE_GETTID
|
156
|
-
native_thread_id = gettid();
|
157
|
-
#else
|
158
|
-
// Note: We could use the current_thread_serial as a crappy fallback, but this would make getting thread names
|
159
|
-
// not work very well
|
160
|
-
#error No native thread id available?
|
161
|
-
#endif
|
162
|
-
|
163
|
-
state->native_thread_id = native_thread_id;
|
158
|
+
state->native_thread_id = current_native_thread_id();
|
164
159
|
#endif
|
165
160
|
}
|
166
161
|
|
@@ -174,8 +169,9 @@ static VALUE tracing_init_local_storage(UNUSED_ARG VALUE _self, VALUE threads) {
|
|
174
169
|
return Qtrue;
|
175
170
|
}
|
176
171
|
|
177
|
-
static VALUE tracing_start(UNUSED_ARG VALUE _self, VALUE output_path) {
|
172
|
+
static VALUE tracing_start(UNUSED_ARG VALUE _self, VALUE output_path, VALUE os_threads_view_enabled_arg) {
|
178
173
|
Check_Type(output_path, T_STRING);
|
174
|
+
if (os_threads_view_enabled_arg != Qtrue && os_threads_view_enabled_arg != Qfalse) rb_raise(rb_eArgError, "os_threads_view_enabled must be true/false");
|
179
175
|
|
180
176
|
trim_all_seen_threads(Qnil);
|
181
177
|
|
@@ -183,13 +179,26 @@ static VALUE tracing_start(UNUSED_ARG VALUE _self, VALUE output_path) {
|
|
183
179
|
output_file = fopen(StringValuePtr(output_path), "w");
|
184
180
|
if (output_file == NULL) rb_syserr_fail(errno, "Failed to open GvlTracing output file");
|
185
181
|
|
186
|
-
fprintf(output_file, "[\n");
|
187
|
-
|
188
182
|
thread_local_state *state = GT_CURRENT_THREAD_LOCAL_STATE();
|
189
183
|
started_tracing_at_microseconds = timestamp_microseconds();
|
190
184
|
process_id = getpid();
|
185
|
+
os_threads_view_enabled = (os_threads_view_enabled_arg == Qtrue);
|
186
|
+
|
187
|
+
VALUE ruby_version = rb_const_get(rb_cObject, rb_intern("RUBY_VERSION"));
|
188
|
+
Check_Type(ruby_version, T_STRING);
|
189
|
+
|
190
|
+
fprintf(output_file, "[\n");
|
191
|
+
fprintf(output_file,
|
192
|
+
" {\"ph\": \"M\", \"pid\": %"PRId64", \"name\": \"process_name\", \"args\": {\"name\": \"Ruby threads view (%s)\"}},\n",
|
193
|
+
process_id, StringValuePtr(ruby_version)
|
194
|
+
);
|
195
|
+
|
196
|
+
double now_microseconds = render_event(state, "started_tracing");
|
191
197
|
|
192
|
-
|
198
|
+
if (os_threads_view_enabled) {
|
199
|
+
fprintf(output_file, " {\"ph\": \"M\", \"pid\": %"PRId64", \"name\": \"process_name\", \"args\": {\"name\": \"OS threads view\"}},\n", OS_THREADS_VIEW_PID);
|
200
|
+
render_os_thread_event(state, now_microseconds);
|
201
|
+
}
|
193
202
|
|
194
203
|
current_hook = rb_internal_thread_add_event_hook(
|
195
204
|
on_thread_event,
|
@@ -218,7 +227,9 @@ static VALUE tracing_stop(UNUSED_ARG VALUE _self) {
|
|
218
227
|
rb_tracepoint_disable(gc_tracepoint);
|
219
228
|
gc_tracepoint = Qnil;
|
220
229
|
|
221
|
-
render_event(state, "stopped_tracing");
|
230
|
+
double now_microseconds = render_event(state, "stopped_tracing");
|
231
|
+
if (os_threads_view_enabled) finish_previous_os_thread_event(now_microseconds);
|
232
|
+
|
222
233
|
// closing the json syntax in the output file is handled in GvlTracing.stop code
|
223
234
|
|
224
235
|
if (fclose(output_file) != 0) rb_syserr_fail(errno, "Failed to close GvlTracing output file");
|
@@ -240,7 +251,7 @@ static double timestamp_microseconds(void) {
|
|
240
251
|
|
241
252
|
// Render output using trace event format for perfetto:
|
242
253
|
// https://chromium.googlesource.com/catapult/+/refs/heads/main/docs/trace-event-format.md
|
243
|
-
static
|
254
|
+
static double render_event(thread_local_state *state, const char *event_name) {
|
244
255
|
// Event data
|
245
256
|
double now_microseconds = timestamp_microseconds() - started_tracing_at_microseconds;
|
246
257
|
|
@@ -251,6 +262,7 @@ static void render_event(thread_local_state *state, const char *event_name) {
|
|
251
262
|
// Important note: We've observed some rendering issues in perfetto if the tid or pid are numbers that are "too big",
|
252
263
|
// see https://github.com/ivoanjo/gvl-tracing/pull/4#issuecomment-1196463364 for an example.
|
253
264
|
|
265
|
+
output_mutex_lock();
|
254
266
|
fprintf(output_file,
|
255
267
|
// Finish previous duration
|
256
268
|
" {\"ph\": \"E\", \"pid\": %"PRId64", \"tid\": %d, \"ts\": %f},\n" \
|
@@ -261,6 +273,9 @@ static void render_event(thread_local_state *state, const char *event_name) {
|
|
261
273
|
// Args for second line
|
262
274
|
process_id, thread_id_for(state), now_microseconds, event_name
|
263
275
|
);
|
276
|
+
output_mutex_unlock();
|
277
|
+
|
278
|
+
return now_microseconds;
|
264
279
|
}
|
265
280
|
|
266
281
|
static void on_thread_event(rb_event_flag_t event_id, const rb_internal_thread_event_data_t *event_data, UNUSED_ARG void *_unused2) {
|
@@ -298,7 +313,15 @@ static void on_thread_event(rb_event_flag_t event_id, const rb_internal_thread_e
|
|
298
313
|
case RUBY_INTERNAL_THREAD_EVENT_STARTED: event_name = "started"; break;
|
299
314
|
case RUBY_INTERNAL_THREAD_EVENT_EXITED: event_name = "died"; break;
|
300
315
|
};
|
301
|
-
render_event(state, event_name);
|
316
|
+
double now_microseconds = render_event(state, event_name);
|
317
|
+
|
318
|
+
if (os_threads_view_enabled) {
|
319
|
+
if (event_id == RUBY_INTERNAL_THREAD_EVENT_RESUMED) {
|
320
|
+
render_os_thread_event(state, now_microseconds);
|
321
|
+
} else if (event_id == RUBY_INTERNAL_THREAD_EVENT_SUSPENDED || event_id == RUBY_INTERNAL_THREAD_EVENT_EXITED) {
|
322
|
+
finish_previous_os_thread_event(now_microseconds);
|
323
|
+
}
|
324
|
+
}
|
302
325
|
}
|
303
326
|
|
304
327
|
static void on_gc_event(VALUE tpval, UNUSED_ARG void *_unused1) {
|
@@ -337,6 +360,18 @@ static inline void all_seen_threads_mutex_unlock(void) {
|
|
337
360
|
if (error) rb_syserr_fail(error, "Failed to unlock GvlTracing mutex");
|
338
361
|
}
|
339
362
|
|
363
|
+
static inline void output_mutex_lock(void) {
|
364
|
+
int error = pthread_mutex_lock(&output_mutex);
|
365
|
+
// Can't raise exceptions on error since it gets used from outside the GVL
|
366
|
+
if (error) fprintf(stderr, "Failed to lock the GvlTracing output_mutex");
|
367
|
+
}
|
368
|
+
|
369
|
+
static inline void output_mutex_unlock(void) {
|
370
|
+
int error = pthread_mutex_unlock(&output_mutex);
|
371
|
+
// Can't raise exceptions on error since it gets used from outside the GVL
|
372
|
+
if (error) fprintf(stderr, "Failed to unlock the GvlTracing output_mutex");
|
373
|
+
}
|
374
|
+
|
340
375
|
#ifdef RUBY_3_3_PLUS
|
341
376
|
static inline thread_local_state *GT_LOCAL_STATE(VALUE thread, bool allocate) {
|
342
377
|
thread_local_state *state = rb_internal_thread_specific_get(thread, thread_storage_key);
|
@@ -414,3 +449,52 @@ static VALUE trim_all_seen_threads(UNUSED_ARG VALUE _self) {
|
|
414
449
|
all_seen_threads_mutex_unlock();
|
415
450
|
return Qtrue;
|
416
451
|
}
|
452
|
+
|
453
|
+
// Creates an event that follows the current native thread. Note that this assumes that whatever event
|
454
|
+
// made us call `render_os_thread_event` is an event about the current (native) thread; if the event is not about the
|
455
|
+
// current thread, the results will be incorrect.
|
456
|
+
static void render_os_thread_event(thread_local_state *state, double now_microseconds) {
|
457
|
+
finish_previous_os_thread_event(now_microseconds);
|
458
|
+
|
459
|
+
// Hack: If we name threads as "Thread N", perfetto seems to color them all with the same color, which looks awful.
|
460
|
+
// I did not check the code, but in practice perfetto seems to be doing some kind of hashing based only on regular
|
461
|
+
// chars, so here we append a different letter to each thread to cause the color hashing to differ.
|
462
|
+
char color_suffix_hack = ('a' + (thread_id_for(state) % 26));
|
463
|
+
|
464
|
+
output_mutex_lock();
|
465
|
+
fprintf(output_file,
|
466
|
+
" {\"ph\": \"B\", \"pid\": %"PRId64", \"tid\": %u, \"ts\": %f, \"name\": \"Thread %d (%c)\"},\n",
|
467
|
+
OS_THREADS_VIEW_PID, current_native_thread_id(), now_microseconds, thread_id_for(state), color_suffix_hack
|
468
|
+
);
|
469
|
+
output_mutex_unlock();
|
470
|
+
}
|
471
|
+
|
472
|
+
static void finish_previous_os_thread_event(double now_microseconds) {
|
473
|
+
output_mutex_lock();
|
474
|
+
fprintf(output_file,
|
475
|
+
" {\"ph\": \"E\", \"pid\": %"PRId64", \"tid\": %u, \"ts\": %f},\n",
|
476
|
+
OS_THREADS_VIEW_PID, current_native_thread_id(), now_microseconds
|
477
|
+
);
|
478
|
+
output_mutex_unlock();
|
479
|
+
}
|
480
|
+
|
481
|
+
static inline uint32_t current_native_thread_id(void) {
|
482
|
+
uint32_t native_thread_id = 0;
|
483
|
+
|
484
|
+
#ifdef HAVE_PTHREAD_THREADID_NP
|
485
|
+
uint64_t full_native_thread_id;
|
486
|
+
pthread_threadid_np(pthread_self(), &full_native_thread_id);
|
487
|
+
// Note: `pthread_threadid_np` is declared as taking in a `uint64_t` but I don't think macOS uses such really
|
488
|
+
// high thread ids, and anyway perfetto doesn't like full 64-bit ids for threads so let's go with a simplification
|
489
|
+
// for now.
|
490
|
+
native_thread_id = (uint32_t) full_native_thread_id;
|
491
|
+
#elif HAVE_GETTID
|
492
|
+
native_thread_id = gettid();
|
493
|
+
#else
|
494
|
+
// Note: We could use a native thread-local crappy fallback, but I think the two above alternatives are available
|
495
|
+
// on all OSs that support the GVL tracing API.
|
496
|
+
#error No native thread id available?
|
497
|
+
#endif
|
498
|
+
|
499
|
+
return native_thread_id;
|
500
|
+
}
|
data/gvl-tracing.gemspec
CHANGED
@@ -42,7 +42,8 @@ Gem::Specification.new do |spec|
|
|
42
42
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
43
43
|
spec.files = Dir.chdir(__dir__) do
|
44
44
|
`git ls-files -z`.split("\x0").reject do |f|
|
45
|
-
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features|examples)/|\.(?:git|travis|circleci)|appveyor)})
|
45
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features|examples)/|\.(?:git|travis|circleci)|appveyor)}) ||
|
46
|
+
[".editorconfig", ".ruby-version", ".standard.yml", "gems.rb", "Rakefile"].include?(f)
|
46
47
|
end
|
47
48
|
end
|
48
49
|
spec.require_paths = ["lib", "ext"]
|
data/lib/gvl-tracing.rb
CHANGED
data/lib/gvl_tracing/version.rb
CHANGED
data/preview.png
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gvl-tracing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivo Anjo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-08 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -18,16 +18,11 @@ extensions:
|
|
18
18
|
- ext/gvl_tracing_native_extension/extconf.rb
|
19
19
|
extra_rdoc_files: []
|
20
20
|
files:
|
21
|
-
- ".editorconfig"
|
22
|
-
- ".ruby-version"
|
23
|
-
- ".standard.yml"
|
24
21
|
- CODE_OF_CONDUCT.adoc
|
25
22
|
- LICENSE
|
26
23
|
- README.adoc
|
27
|
-
- Rakefile
|
28
24
|
- ext/gvl_tracing_native_extension/extconf.rb
|
29
25
|
- ext/gvl_tracing_native_extension/gvl_tracing.c
|
30
|
-
- gems.rb
|
31
26
|
- gvl-tracing.gemspec
|
32
27
|
- lib/gvl-tracing.rb
|
33
28
|
- lib/gvl_tracing/sleep_tracking.rb
|
@@ -53,7 +48,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
53
48
|
- !ruby/object:Gem::Version
|
54
49
|
version: '0'
|
55
50
|
requirements: []
|
56
|
-
rubygems_version: 3.
|
51
|
+
rubygems_version: 3.4.1
|
57
52
|
signing_key:
|
58
53
|
specification_version: 4
|
59
54
|
summary: Get a timeline view of Global VM Lock usage in your Ruby app
|
data/.editorconfig
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
# EditorConfig is awesome: https://EditorConfig.org
|
2
|
-
|
3
|
-
# top-most EditorConfig file
|
4
|
-
root = true
|
5
|
-
|
6
|
-
# Unix-style newlines with a newline ending every file
|
7
|
-
[*]
|
8
|
-
end_of_line = lf
|
9
|
-
insert_final_newline = true
|
10
|
-
trim_trailing_whitespace = true
|
11
|
-
|
12
|
-
[*.h]
|
13
|
-
indent_style = space
|
14
|
-
indent_size = 2
|
15
|
-
|
16
|
-
[*.c]
|
17
|
-
indent_style = space
|
18
|
-
indent_size = 2
|
19
|
-
|
20
|
-
[*.yml]
|
21
|
-
indent_style = space
|
22
|
-
indent_size = 2
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
ruby-3.2.2
|
data/.standard.yml
DELETED
data/Rakefile
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
# gvl-tracing: Ruby gem for getting a timelinew view of GVL usage
|
2
|
-
# Copyright (c) 2022 Ivo Anjo <ivo@ivoanjo.me>
|
3
|
-
#
|
4
|
-
# This file is part of gvl-tracing.
|
5
|
-
#
|
6
|
-
# MIT License
|
7
|
-
#
|
8
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
9
|
-
# of this software and associated documentation files (the "Software"), to deal
|
10
|
-
# in the Software without restriction, including without limitation the rights
|
11
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12
|
-
# copies of the Software, and to permit persons to whom the Software is
|
13
|
-
# furnished to do so, subject to the following conditions:
|
14
|
-
#
|
15
|
-
# The above copyright notice and this permission notice shall be included in all
|
16
|
-
# copies or substantial portions of the Software.
|
17
|
-
#
|
18
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
21
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
24
|
-
# SOFTWARE.
|
25
|
-
|
26
|
-
# frozen_string_literal: true
|
27
|
-
|
28
|
-
require "bundler/gem_tasks"
|
29
|
-
require "standard/rake"
|
30
|
-
require "rake/extensiontask"
|
31
|
-
require "rspec/core/rake_task"
|
32
|
-
|
33
|
-
Rake::ExtensionTask.new("gvl_tracing_native_extension")
|
34
|
-
RSpec::Core::RakeTask.new(:spec)
|
35
|
-
|
36
|
-
task default: [:compile, :"standard:fix", :spec]
|
data/gems.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
source "https://rubygems.org"
|
4
|
-
|
5
|
-
gemspec
|
6
|
-
|
7
|
-
gem "rake", "~> 13.0"
|
8
|
-
gem "rake-compiler", "~> 1.2"
|
9
|
-
gem "pry"
|
10
|
-
gem "pry-byebug"
|
11
|
-
gem "rspec"
|
12
|
-
gem "standard", "~> 1.33"
|
13
|
-
gem "concurrent-ruby"
|
14
|
-
gem "benchmark-ips", "~> 2.13"
|