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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 42d6e3f8ea2cc420e17a413a62fba51ccb6c2b90dac11138186e9f4d203bed51
4
- data.tar.gz: 97576f44774bb991699152d36140714b792e17ced8a7ea48d1210f0c8d94b1df
3
+ metadata.gz: 5ffb320bec5fdc8a0d4940d8b370af1607a20383e1a9a8f939cc759588ca6627
4
+ data.tar.gz: 223bee0c124c17296b8386bbdda94406f91b84ad0adcf3acd09921424bb8eaf8
5
5
  SHA512:
6
- metadata.gz: ae23c00ab1f94c2af17753f5ba847690ebea31cb0d3f23134080ad34a475686ac0d9872fa56025a1fab8135c5ee57c58e19675bbc08160c9444a8d30edb847db
7
- data.tar.gz: 54e1694fd5d16935c98a6b838fdf188427cf645f0fe00ac08a7323609c70f01721d9836b80c6bdf2096ee7341d4d39a44f713b20a770470072c72c48887564c3
6
+ metadata.gz: 1c988c2e9d2c17925b178e4201f99530e75328cda648b3e3b50664e1d751ff5ad086139293a22dab5a54ae18e86bdd7d6e14064f4a4833eae18d3d948f134f20
7
+ data.tar.gz: 3b56ad91bf7784d0c61e4d321964eeaaae8ca97ec6c6c86c1934e8e95ad9d720b00933a7b0f7e91ec45e7ffd2a07665800c6f616250b7251318dc889a5ba94ca
data/.rubocop.yml CHANGED
@@ -22,6 +22,15 @@ Style/GlobalVars:
22
22
  Exclude:
23
23
  - ext/**/extconf.rb
24
24
 
25
+ Style/EmptyMethod:
26
+ Enabled: false
27
+
28
+ Style/IfUnlessModifier:
29
+ Enabled: false
30
+
31
+ Style/GuardClause:
32
+ Enabled: false
33
+
25
34
  Style/Documentation:
26
35
  Enabled: false
27
36
 
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gvltools (0.1.0)
4
+ gvltools (0.3.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -32,6 +32,7 @@ GEM
32
32
  unicode-display_width (2.1.0)
33
33
 
34
34
  PLATFORMS
35
+ aarch64-linux
35
36
  arm64-darwin-21
36
37
  arm64-darwin-22
37
38
  x86_64-linux
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "mkmf"
4
- if RUBY_ENGINE == "ruby" && have_func("rb_internal_thread_add_event_hook", ["ruby/thread.h"])
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 <ruby/atomic.h>
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 rb_atomic_t gt_time_diff_ns(struct timespec before, struct timespec after) {
35
- rb_atomic_t total = 0;
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 rb_atomic_t global_timer_total = 0;
71
- static THREAD_LOCAL_SPECIFIER uint64_t local_timer_total = 0;
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 UINT2NUM(global_timer_total);
77
+ return ULL2NUM(global_timer_total);
76
78
  }
77
79
 
78
80
  static VALUE global_timer_reset(VALUE module) {
79
- RUBY_ATOMIC_SET(global_timer_total, 0);
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 rb_atomic_t waiting_threads_total = 0;
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 UINT2NUM(waiting_threads_total);
100
+ return ULL2NUM(waiting_threads_total);
97
101
  }
98
102
 
99
103
  static VALUE waiting_threads_reset(VALUE module) {
100
- RUBY_ATOMIC_SET(waiting_threads_total, 0);
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
- RUBY_ATOMIC_INC(waiting_threads_total);
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
- RUBY_ATOMIC_DEC(waiting_threads_total);
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(&current_time);
141
- rb_atomic_t diff = gt_time_diff_ns(timer_ready_at, current_time);
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
- RUBY_ATOMIC_ADD(global_timer_total, diff);
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, "reset", waiting_threads_reset, 0);
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
  }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GVLTools
4
- VERSION = "0.1.0"
4
+ VERSION = "0.3.0"
5
5
  end
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.1.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-01-17 00:00:00.000000000 Z
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.1
70
+ rubygems_version: 3.4.10
71
71
  signing_key:
72
72
  specification_version: 4
73
73
  summary: Set of GVL instrumentation tools