gvltools 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.
- 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
|