gvltools 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +9 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +2 -1
- data/ext/gvltools/extconf.rb +4 -1
- data/ext/gvltools/instrumentation.c +23 -15
- data/lib/gvltools/version.rb +1 -1
- data/lib/gvltools.rb +19 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ffb320bec5fdc8a0d4940d8b370af1607a20383e1a9a8f939cc759588ca6627
|
4
|
+
data.tar.gz: 223bee0c124c17296b8386bbdda94406f91b84ad0adcf3acd09921424bb8eaf8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c988c2e9d2c17925b178e4201f99530e75328cda648b3e3b50664e1d751ff5ad086139293a22dab5a54ae18e86bdd7d6e14064f4a4833eae18d3d948f134f20
|
7
|
+
data.tar.gz: 3b56ad91bf7784d0c61e4d321964eeaaae8ca97ec6c6c86c1934e8e95ad9d720b00933a7b0f7e91ec45e7ffd2a07665800c6f616250b7251318dc889a5ba94ca
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.3.0] - 2023-04-11
|
4
|
+
|
5
|
+
- Automatically reset the `WaitingThreads` counter when enabling it (#7).
|
6
|
+
- Disallow resetting the `WaitingThreads` counter when it is active (#7).
|
7
|
+
|
8
|
+
## [0.2.0] - 2023-03-28
|
9
|
+
|
10
|
+
- Use C11 atomics instead of MRI's `rb_atomic_t`.
|
11
|
+
|
3
12
|
## [0.1.0] - 2022-06-14
|
4
13
|
|
5
14
|
- Initial release
|
data/Gemfile.lock
CHANGED
data/ext/gvltools/extconf.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "mkmf"
|
4
|
-
if RUBY_ENGINE == "ruby" &&
|
4
|
+
if RUBY_ENGINE == "ruby" &&
|
5
|
+
have_header("stdatomic.h") &&
|
6
|
+
have_func("rb_internal_thread_add_event_hook", ["ruby/thread.h"])
|
7
|
+
|
5
8
|
$CFLAGS << " -O3 -Wall "
|
6
9
|
create_makefile("gvltools/instrumentation")
|
7
10
|
else
|
@@ -1,7 +1,9 @@
|
|
1
1
|
#include <time.h>
|
2
2
|
#include <ruby.h>
|
3
3
|
#include <ruby/thread.h>
|
4
|
-
#include <
|
4
|
+
#include <stdatomic.h>
|
5
|
+
|
6
|
+
typedef unsigned long long counter_t;
|
5
7
|
|
6
8
|
// Metrics
|
7
9
|
static rb_internal_thread_event_hook_t *gt_hook = NULL;
|
@@ -31,8 +33,8 @@ static inline void gt_gettime(struct timespec *time) {
|
|
31
33
|
}
|
32
34
|
}
|
33
35
|
|
34
|
-
static inline
|
35
|
-
|
36
|
+
static inline counter_t gt_time_diff_ns(struct timespec before, struct timespec after) {
|
37
|
+
counter_t total = 0;
|
36
38
|
total += (after.tv_nsec - before.tv_nsec);
|
37
39
|
total += (after.tv_sec - before.tv_sec) * SECONDS_TO_NANOSECONDS;
|
38
40
|
return total;
|
@@ -67,16 +69,16 @@ static VALUE gt_disable_metric(VALUE module, VALUE metric) {
|
|
67
69
|
}
|
68
70
|
|
69
71
|
// GVLTools::LocalTimer and GVLTools::GlobalTimer
|
70
|
-
static
|
71
|
-
static THREAD_LOCAL_SPECIFIER
|
72
|
+
static _Atomic counter_t global_timer_total = 0;
|
73
|
+
static THREAD_LOCAL_SPECIFIER counter_t local_timer_total = 0;
|
72
74
|
static THREAD_LOCAL_SPECIFIER struct timespec timer_ready_at = {0};
|
73
75
|
|
74
76
|
static VALUE global_timer_monotonic_time(VALUE module) {
|
75
|
-
return
|
77
|
+
return ULL2NUM(global_timer_total);
|
76
78
|
}
|
77
79
|
|
78
80
|
static VALUE global_timer_reset(VALUE module) {
|
79
|
-
|
81
|
+
global_timer_total = 0;
|
80
82
|
return Qtrue;
|
81
83
|
}
|
82
84
|
|
@@ -90,14 +92,17 @@ static VALUE local_timer_reset(VALUE module) {
|
|
90
92
|
}
|
91
93
|
|
92
94
|
// Thread counts
|
93
|
-
static
|
95
|
+
static _Atomic counter_t waiting_threads_total = 0;
|
96
|
+
static _Atomic counter_t waiting_threads_current_generation = 1;
|
97
|
+
static THREAD_LOCAL_SPECIFIER counter_t waiting_threads_ready_generation = 0;
|
94
98
|
|
95
99
|
static VALUE waiting_threads_count(VALUE module) {
|
96
|
-
return
|
100
|
+
return ULL2NUM(waiting_threads_total);
|
97
101
|
}
|
98
102
|
|
99
103
|
static VALUE waiting_threads_reset(VALUE module) {
|
100
|
-
|
104
|
+
waiting_threads_current_generation++;
|
105
|
+
waiting_threads_total = 0;
|
101
106
|
return Qtrue;
|
102
107
|
}
|
103
108
|
|
@@ -120,7 +125,8 @@ static void gt_thread_callback(rb_event_flag_t event, const rb_internal_thread_e
|
|
120
125
|
if (!was_ready) was_ready = true;
|
121
126
|
|
122
127
|
if (ENABLED(WAITING_THREADS)) {
|
123
|
-
|
128
|
+
waiting_threads_ready_generation = waiting_threads_current_generation;
|
129
|
+
waiting_threads_total++;
|
124
130
|
}
|
125
131
|
|
126
132
|
if (ENABLED(TIMER_GLOBAL | TIMER_LOCAL)) {
|
@@ -132,20 +138,22 @@ static void gt_thread_callback(rb_event_flag_t event, const rb_internal_thread_e
|
|
132
138
|
if (!was_ready) break; // In case we registered the hook while some threads were already waiting on the GVL
|
133
139
|
|
134
140
|
if (ENABLED(WAITING_THREADS)) {
|
135
|
-
|
141
|
+
if (waiting_threads_ready_generation == waiting_threads_current_generation) {
|
142
|
+
waiting_threads_total--;
|
143
|
+
}
|
136
144
|
}
|
137
145
|
|
138
146
|
if (ENABLED(TIMER_GLOBAL | TIMER_LOCAL)) {
|
139
147
|
struct timespec current_time;
|
140
148
|
gt_gettime(¤t_time);
|
141
|
-
|
149
|
+
counter_t diff = gt_time_diff_ns(timer_ready_at, current_time);
|
142
150
|
|
143
151
|
if (ENABLED(TIMER_LOCAL)) {
|
144
152
|
local_timer_total += diff;
|
145
153
|
}
|
146
154
|
|
147
155
|
if (ENABLED(TIMER_GLOBAL)) {
|
148
|
-
|
156
|
+
global_timer_total += diff;
|
149
157
|
}
|
150
158
|
}
|
151
159
|
}
|
@@ -170,6 +178,6 @@ void Init_instrumentation(void) {
|
|
170
178
|
rb_define_singleton_method(rb_mLocalTimer, "monotonic_time", local_timer_monotonic_time, 0);
|
171
179
|
|
172
180
|
VALUE rb_mWaitingThreads = rb_const_get(rb_mGVLTools, rb_intern("WaitingThreads"));
|
173
|
-
rb_define_singleton_method(rb_mWaitingThreads, "
|
181
|
+
rb_define_singleton_method(rb_mWaitingThreads, "_reset", waiting_threads_reset, 0);
|
174
182
|
rb_define_singleton_method(rb_mWaitingThreads, "count", waiting_threads_count, 0);
|
175
183
|
}
|
data/lib/gvltools/version.rb
CHANGED
data/lib/gvltools.rb
CHANGED
@@ -96,8 +96,27 @@ module GVLTools
|
|
96
96
|
end
|
97
97
|
alias_method :count, :count
|
98
98
|
|
99
|
+
def enable
|
100
|
+
unless enabled?
|
101
|
+
reset
|
102
|
+
end
|
103
|
+
super
|
104
|
+
end
|
105
|
+
|
106
|
+
def reset
|
107
|
+
if enabled?
|
108
|
+
raise Error, "can't reset WaitingThreads counter while it is active"
|
109
|
+
else
|
110
|
+
_reset
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
99
114
|
private
|
100
115
|
|
116
|
+
def _reset
|
117
|
+
end
|
118
|
+
alias_method :_reset, :_reset # to be redefined from C.
|
119
|
+
|
101
120
|
def metric
|
102
121
|
WAITING_THREADS
|
103
122
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gvltools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean Boussier
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-04-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -67,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
requirements: []
|
70
|
-
rubygems_version: 3.4.
|
70
|
+
rubygems_version: 3.4.10
|
71
71
|
signing_key:
|
72
72
|
specification_version: 4
|
73
73
|
summary: Set of GVL instrumentation tools
|