gvl-tracing 0.2.0 → 1.0.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: 1adc64642ec1cb371df66afa9f928cafe106349f981a3b8ec643232a0618b769
4
- data.tar.gz: 9b250c7a07df1f9a1f907100554fa74eba043edb639ad1cc777b33ba705d98f3
3
+ metadata.gz: 64d9b437af5f15e4a865a580486df67974e42b22b9836fa37e4de608597bf8d8
4
+ data.tar.gz: 52e7ecb9f89e613acd619a4225cfa2ac1f83cbf42e9173d59ccb91db09a1e7c6
5
5
  SHA512:
6
- metadata.gz: 5016d9734e5eeef9578fc83211bb68cbc26f68f1b93b41c3ff0fbd9f5a3b93745cb7de23c69cc228a903b17db565ee369ec3d41f7d9575e3107a04a9bf6368a0
7
- data.tar.gz: 821d89427465c6496e09a773a1277d35388d4205fd5e0e5f054fd8da8d1a46d902e4f464764a0e5891bb9ebb63451295ea2bf1986c085616b2ff60926dcbde7a
6
+ metadata.gz: 529be0892156b7060427359d3e4386ed4f2bf0d96a3671896a6fcde4d347370e061567b8f88718ec894520ff9dc4b3bc667810da6d16b3ed171ef004ea3ecaf3
7
+ data.tar.gz: 8702d542f6962be8f0b471ed15e66c6ff4da1a41eadd121edacb3ade280109eeb219b4b7a6c1786ba13518948406f5182102af1fc363c7327e9a3c5bfe5e2cd4
data/README.adoc CHANGED
@@ -10,7 +10,7 @@ image::preview.png[]
10
10
 
11
11
  See my blog post https://ivoanjo.me/blog/2022/07/17/tracing-ruby-global-vm-lock/[tracing ruby's (global) vm lock] for more details!
12
12
 
13
- NOTE: This gem only works on Ruby 3.2 and above because it depends on the new https://github.com/ruby/ruby/pull/5500[GVL Instrumentation API]. See below for an easy way to run Ruby 3.2 inside docker.
13
+ NOTE: This gem only works on Ruby 3.2 and above because it depends on the https://github.com/ruby/ruby/pull/5500[GVL Instrumentation API].
14
14
 
15
15
  == Quickest start
16
16
 
@@ -43,26 +43,6 @@ To do so:
43
43
  1. Download link:https://github.com/ivoanjo/gvl-tracing/blob/master/examples/example1.json.gz?raw=true[`examples/example1.json.gz`]
44
44
  2. Navigate to https://ui.perfetto.dev/ and use the **Open trace file** option to load the file
45
45
 
46
- == Quick start using docker
47
-
48
- The `gvl-tracing` gem requires Ruby 3.2, which is still under development. If you have docker installed on your machine, you can use the https://hub.docker.com/r/rubylang/ruby[ruby-lang development images] to try it out.
49
-
50
- Here's how you can use them:
51
-
52
- [source,bash]
53
- ----
54
- $ cd my_ruby_app/
55
- $ docker run -v $(pwd):/app -it rubylang/ruby:master-focal
56
- root@0e0b07edf906:/# cd app/
57
- root@0e0b07edf906:/app# ruby -v
58
- ruby 3.2.0dev (2022-07-23T12:42:05Z master 721d154e2f) [x86_64-linux]
59
- root@0e0b07edf906:/app# gem install gvl-tracing
60
- Building native extensions. This could take a while...
61
- Successfully installed gvl-tracing-0.1.1
62
- 1 gem installed
63
- root@0e0b07edf906:/app# ruby <your app>
64
- ----
65
-
66
46
  == Installation
67
47
 
68
48
  Install the gem and add to the application's `Gemfile` or `gems.rb` file by executing:
@@ -32,4 +32,10 @@ end
32
32
 
33
33
  require "mkmf"
34
34
 
35
+ have_func("gettid", "unistd.h")
36
+ have_header("pthread.h")
37
+ have_func("pthread_getname_np", "pthread.h")
38
+ have_func("pthread_threadid_np", "pthread.h")
39
+
40
+ create_header
35
41
  create_makefile "gvl_tracing_native_extension"
@@ -31,6 +31,16 @@
31
31
  #include <stdbool.h>
32
32
  #include <sys/types.h>
33
33
 
34
+ #include "extconf.h"
35
+
36
+ #ifdef HAVE_PTHREAD_H
37
+ #include <pthread.h>
38
+ #endif
39
+
40
+ #ifdef HAVE_GETTID
41
+ #include <unistd.h>
42
+ #endif
43
+
34
44
  static VALUE tracing_start(VALUE _self, VALUE output_path);
35
45
  static VALUE tracing_stop(VALUE _self);
36
46
  static double timestamp_microseconds(void);
@@ -59,12 +69,31 @@ void Init_gvl_tracing_native_extension(void) {
59
69
  rb_define_singleton_method(gvl_tracing_module, "stop", tracing_stop, 0);
60
70
  }
61
71
 
62
- static inline unsigned int current_thread_id(void) {
63
- if (!current_thread_serial_set) {
64
- current_thread_serial_set = true;
65
- current_thread_serial = RUBY_ATOMIC_FETCH_ADD(thread_serial, 1);
66
- }
67
- return (unsigned int)current_thread_serial;
72
+ static inline void initialize_thread_id(void) {
73
+ current_thread_serial_set = true;
74
+ current_thread_serial = RUBY_ATOMIC_FETCH_ADD(thread_serial, 1);
75
+ }
76
+
77
+ static inline void render_thread_metadata(void) {
78
+ uint64_t native_thread_id = 0;
79
+ #ifdef HAVE_GETTID
80
+ native_thread_id = gettid();
81
+ #elif HAVE_PTHREAD_THREADID_NP
82
+ pthread_threadid_np(pthread_self(), &native_thread_id);
83
+ #else
84
+ native_thread_id = current_thread_serial; // TODO: Better fallback for Windows?
85
+ #endif
86
+
87
+ char native_thread_name_buffer[64] = "(unnamed)";
88
+
89
+ #ifdef HAVE_PTHREAD_GETNAME_NP
90
+ pthread_getname_np(pthread_self(), native_thread_name_buffer, sizeof(native_thread_name_buffer));
91
+ #endif
92
+
93
+ fprintf(output_file,
94
+ " {\"ph\": \"M\", \"pid\": %u, \"tid\": %u, \"name\": \"thread_name\", \"args\": {\"name\": \"%lu %s\"}},\n",
95
+ process_id, current_thread_serial, native_thread_id, native_thread_name_buffer
96
+ );
68
97
  }
69
98
 
70
99
  static VALUE tracing_start(VALUE _self, VALUE output_path) {
@@ -134,7 +163,13 @@ static double timestamp_microseconds(void) {
134
163
  static void render_event(const char *event_name) {
135
164
  // Event data
136
165
  double now_microseconds = timestamp_microseconds() - started_tracing_at_microseconds;
137
- unsigned int thread_id = current_thread_id();
166
+
167
+ if (!current_thread_serial_set) {
168
+ initialize_thread_id();
169
+ render_thread_metadata();
170
+ }
171
+
172
+ unsigned int thread_id = current_thread_serial;
138
173
 
139
174
  // Each event is converted into two events in the output: one that signals the end of the previous event
140
175
  // (whatever it was), and one that signals the start of the actual event we're processing.
data/gvl-tracing.gemspec CHANGED
@@ -36,13 +36,13 @@ Gem::Specification.new do |spec|
36
36
  spec.summary = "Get a timeline view of Global VM Lock usage in your Ruby app"
37
37
  spec.homepage = "https://github.com/ivoanjo/gvl-tracing"
38
38
  spec.license = "MIT"
39
- spec.required_ruby_version = ">= 3.2.0.dev"
39
+ spec.required_ruby_version = ">= 3.2.0"
40
40
 
41
41
  # Specify which files should be added to the gem when it is released.
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)/|\.(?:git|travis|circleci)|appveyor)})
45
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features|examples)/|\.(?:git|travis|circleci)|appveyor)})
46
46
  end
47
47
  end
48
48
  spec.require_paths = ["lib", "ext"]
@@ -26,5 +26,5 @@
26
26
  # frozen_string_literal: true
27
27
 
28
28
  module GvlTracing
29
- VERSION = "0.2.0"
29
+ VERSION = "1.0.0"
30
30
  end
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: 0.2.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivo Anjo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-27 00:00:00.000000000 Z
11
+ date: 2023-02-11 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -24,14 +24,6 @@ files:
24
24
  - LICENSE
25
25
  - README.adoc
26
26
  - Rakefile
27
- - examples/example1.json.gz
28
- - examples/example1.rb
29
- - examples/example2.json.gz
30
- - examples/example2.rb
31
- - examples/example3.json.gz
32
- - examples/example3.rb
33
- - examples/gc.json.gz
34
- - examples/gc.rb
35
27
  - ext/gvl_tracing_native_extension/extconf.rb
36
28
  - ext/gvl_tracing_native_extension/gvl_tracing.c
37
29
  - gems.rb
@@ -52,14 +44,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
52
44
  requirements:
53
45
  - - ">="
54
46
  - !ruby/object:Gem::Version
55
- version: 3.2.0.dev
47
+ version: 3.2.0
56
48
  required_rubygems_version: !ruby/object:Gem::Requirement
57
49
  requirements:
58
50
  - - ">="
59
51
  - !ruby/object:Gem::Version
60
52
  version: '0'
61
53
  requirements: []
62
- rubygems_version: 3.4.0.dev
54
+ rubygems_version: 3.4.1
63
55
  signing_key:
64
56
  specification_version: 4
65
57
  summary: Get a timeline view of Global VM Lock usage in your Ruby app
Binary file
data/examples/example1.rb DELETED
@@ -1,18 +0,0 @@
1
- require "gvl-tracing"
2
-
3
- def fib(n)
4
- return n if n <= 1
5
- fib(n - 1) + fib(n - 2)
6
- end
7
-
8
- GvlTracing.start("example1.json")
9
-
10
- Thread.new { sleep(0.05) while true }
11
-
12
- sleep(0.05)
13
-
14
- 3.times.map { Thread.new { fib(37) } }.map(&:join)
15
-
16
- sleep(0.05)
17
-
18
- GvlTracing.stop
Binary file
data/examples/example2.rb DELETED
@@ -1,14 +0,0 @@
1
- require "gvl-tracing"
2
-
3
- def fib(n)
4
- return n if n <= 1
5
- fib(n - 1) + fib(n - 2)
6
- end
7
-
8
- GvlTracing.start("example2.json")
9
-
10
- other_thread = Thread.new { fib(37) } # runs in other thread
11
- fib(37) # runs in main thread
12
-
13
- other_thread.join
14
- GvlTracing.stop
Binary file
data/examples/example3.rb DELETED
@@ -1,14 +0,0 @@
1
- require "gvl-tracing"
2
-
3
- def fib(n)
4
- return n if n <= 1
5
- fib(n - 1) + fib(n - 2)
6
- end
7
-
8
- GvlTracing.start("example3.json")
9
-
10
- other_ractor = Ractor.new { fib(37) } # runs in other ractor
11
- fib(37) # runs in main thread
12
-
13
- other_ractor.take
14
- GvlTracing.stop
data/examples/gc.json.gz DELETED
Binary file
data/examples/gc.rb DELETED
@@ -1,13 +0,0 @@
1
- require "gvl-tracing"
2
-
3
- def alloc(n)
4
- n.times { Object.new }
5
- end
6
-
7
- GvlTracing.start("gc.json")
8
-
9
- 3.times.map { Thread.new { alloc(100_000) } }.map(&:join)
10
-
11
- sleep(0.05)
12
-
13
- GvlTracing.stop