gvl-tracing 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +22 -0
- data/.standard.yml +5 -0
- data/CODE_OF_CONDUCT.adoc +134 -0
- data/LICENSE +21 -0
- data/README.adoc +87 -0
- data/Rakefile +34 -0
- data/examples/example1.json.gz +0 -0
- data/examples/example1.rb +18 -0
- data/ext/gvl_tracing_native_extension/extconf.rb +35 -0
- data/ext/gvl_tracing_native_extension/gvl_tracing.c +134 -0
- data/gems.rb +10 -0
- data/gvl-tracing.gemspec +50 -0
- data/lib/gvl-tracing.rb +33 -0
- data/lib/gvl_tracing/version.rb +30 -0
- data/preview.png +0 -0
- metadata +60 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 851f587fcb3e81728e4691372cf8433b75179e9b14f88b3516380143692b75c1
|
4
|
+
data.tar.gz: 73af09c5163ef3552c0153ea1fc9fc8fea4e8c8de8d531b1e5fccf812d978d6b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c624c191a80faf90efdb37fb5745eaea89ab5737c262f26cacf2ac7491d783de8ad3f4ce381ad98e8c12ed7f8bfbb72b6e476765034c8f40e799afe0578f70c3
|
7
|
+
data.tar.gz: 352d912e2fcd6a899c1747ceab4511eea7a6a3b922436be715a49caa445664d3c60d22afefba8d3ad044b97126dd0b6e8548d66a1a1e7fcc8ed7c30aee466471
|
data/.editorconfig
ADDED
@@ -0,0 +1,22 @@
|
|
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/.standard.yml
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
|
2
|
+
= Contributor Covenant Code of Conduct
|
3
|
+
|
4
|
+
== Our Pledge
|
5
|
+
|
6
|
+
We as members, contributors, and leaders pledge to make participation in our
|
7
|
+
community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
9
|
+
identity and expression, level of experience, education, socio-economic status,
|
10
|
+
nationality, personal appearance, race, caste, color, religion, or sexual
|
11
|
+
identity and orientation.
|
12
|
+
|
13
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
14
|
+
diverse, inclusive, and healthy community.
|
15
|
+
|
16
|
+
== Our Standards
|
17
|
+
|
18
|
+
Examples of behavior that contributes to a positive environment for our
|
19
|
+
community include:
|
20
|
+
|
21
|
+
* Demonstrating empathy and kindness toward other people
|
22
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
23
|
+
* Giving and gracefully accepting constructive feedback
|
24
|
+
* Accepting responsibility and apologizing to those affected by our mistakes,
|
25
|
+
and learning from the experience
|
26
|
+
* Focusing on what is best not just for us as individuals, but for the overall
|
27
|
+
community
|
28
|
+
|
29
|
+
Examples of unacceptable behavior include:
|
30
|
+
|
31
|
+
* The use of sexualized language or imagery, and sexual attention or advances of
|
32
|
+
any kind
|
33
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
34
|
+
* Public or private harassment
|
35
|
+
* Publishing others' private information, such as a physical or email address,
|
36
|
+
without their explicit permission
|
37
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
38
|
+
professional setting
|
39
|
+
|
40
|
+
== Enforcement Responsibilities
|
41
|
+
|
42
|
+
Community leaders are responsible for clarifying and enforcing our standards of
|
43
|
+
acceptable behavior and will take appropriate and fair corrective action in
|
44
|
+
response to any behavior that they deem inappropriate, threatening, offensive,
|
45
|
+
or harmful.
|
46
|
+
|
47
|
+
Community leaders have the right and responsibility to remove, edit, or reject
|
48
|
+
comments, commits, code, wiki edits, issues, and other contributions that are
|
49
|
+
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
50
|
+
decisions when appropriate.
|
51
|
+
|
52
|
+
== Scope
|
53
|
+
|
54
|
+
This Code of Conduct applies within all community spaces, and also applies when
|
55
|
+
an individual is officially representing the community in public spaces.
|
56
|
+
Examples of representing our community include using an official e-mail address,
|
57
|
+
posting via an official social media account, or acting as an appointed
|
58
|
+
representative at an online or offline event.
|
59
|
+
|
60
|
+
== Enforcement
|
61
|
+
|
62
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
63
|
+
reported to the community leaders responsible for enforcement at
|
64
|
+
ivo@ivoanjo.me.
|
65
|
+
All complaints will be reviewed and investigated promptly and fairly.
|
66
|
+
|
67
|
+
All community leaders are obligated to respect the privacy and security of the
|
68
|
+
reporter of any incident.
|
69
|
+
|
70
|
+
== Enforcement Guidelines
|
71
|
+
|
72
|
+
Community leaders will follow these Community Impact Guidelines in determining
|
73
|
+
the consequences for any action they deem in violation of this Code of Conduct:
|
74
|
+
|
75
|
+
=== 1. Correction
|
76
|
+
|
77
|
+
**Community Impact**: Use of inappropriate language or other behavior deemed
|
78
|
+
unprofessional or unwelcome in the community.
|
79
|
+
|
80
|
+
**Consequence**: A private, written warning from community leaders, providing
|
81
|
+
clarity around the nature of the violation and an explanation of why the
|
82
|
+
behavior was inappropriate. A public apology may be requested.
|
83
|
+
|
84
|
+
=== 2. Warning
|
85
|
+
|
86
|
+
**Community Impact**: A violation through a single incident or series of
|
87
|
+
actions.
|
88
|
+
|
89
|
+
**Consequence**: A warning with consequences for continued behavior. No
|
90
|
+
interaction with the people involved, including unsolicited interaction with
|
91
|
+
those enforcing the Code of Conduct, for a specified period of time. This
|
92
|
+
includes avoiding interactions in community spaces as well as external channels
|
93
|
+
like social media. Violating these terms may lead to a temporary or permanent
|
94
|
+
ban.
|
95
|
+
|
96
|
+
=== 3. Temporary Ban
|
97
|
+
|
98
|
+
**Community Impact**: A serious violation of community standards, including
|
99
|
+
sustained inappropriate behavior.
|
100
|
+
|
101
|
+
**Consequence**: A temporary ban from any sort of interaction or public
|
102
|
+
communication with the community for a specified period of time. No public or
|
103
|
+
private interaction with the people involved, including unsolicited interaction
|
104
|
+
with those enforcing the Code of Conduct, is allowed during this period.
|
105
|
+
Violating these terms may lead to a permanent ban.
|
106
|
+
|
107
|
+
=== 4. Permanent Ban
|
108
|
+
|
109
|
+
**Community Impact**: Demonstrating a pattern of violation of community
|
110
|
+
standards, including sustained inappropriate behavior, harassment of an
|
111
|
+
individual, or aggression toward or disparagement of classes of individuals.
|
112
|
+
|
113
|
+
**Consequence**: A permanent ban from any sort of public interaction within the
|
114
|
+
community.
|
115
|
+
|
116
|
+
== Attribution
|
117
|
+
|
118
|
+
This Code of Conduct is adapted from the Contributor Covenant,
|
119
|
+
version 2.1, available at
|
120
|
+
https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
|
121
|
+
|
122
|
+
Community Impact Guidelines were inspired by
|
123
|
+
Mozilla's code of conduct enforcement ladder.
|
124
|
+
|
125
|
+
For answers to common questions about this code of conduct, see the FAQ at
|
126
|
+
https://www.contributor-covenant.org/faq. Translations are available at
|
127
|
+
https://www.contributor-covenant.org/translations.
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
|
134
|
+
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2022 Ivo Anjo
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.adoc
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
= `gvl-tracing`
|
2
|
+
:toc:
|
3
|
+
:toc-placement: macro
|
4
|
+
:toclevels: 4
|
5
|
+
:toc-title:
|
6
|
+
|
7
|
+
A Ruby gem for getting a timeline view of Global VM Lock usage in your Ruby app that can be analyzed using the https://ui.perfetto.dev/[Perfetto UI].
|
8
|
+
|
9
|
+
image::preview.png[]
|
10
|
+
|
11
|
+
See my blog post **FIXME** for more details!
|
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.
|
14
|
+
|
15
|
+
== Quickest start
|
16
|
+
|
17
|
+
You can play with the output of running the following example:
|
18
|
+
|
19
|
+
[source,ruby]
|
20
|
+
----
|
21
|
+
require "gvl-tracing"
|
22
|
+
|
23
|
+
def fib(n)
|
24
|
+
return n if n <= 1
|
25
|
+
fib(n - 1) + fib(n - 2)
|
26
|
+
end
|
27
|
+
|
28
|
+
GvlTracing.start("example1.json")
|
29
|
+
|
30
|
+
Thread.new { sleep(0.05) while true }
|
31
|
+
|
32
|
+
sleep(0.05)
|
33
|
+
|
34
|
+
3.times.map { Thread.new { fib(37) } }.map(&:join)
|
35
|
+
|
36
|
+
sleep(0.05)
|
37
|
+
|
38
|
+
GvlTracing.stop
|
39
|
+
----
|
40
|
+
|
41
|
+
To do so:
|
42
|
+
|
43
|
+
1. Download link:https://github.com/ivoanjo/gvl-tracing/blob/master/examples/example1.json.gz?raw=true[`examples/example1.json.gz`]
|
44
|
+
2. Navigate to https://ui.perfetto.dev/ and use the **Open trace file** option to load the file
|
45
|
+
|
46
|
+
== Quick start using docker
|
47
|
+
|
48
|
+
**FIXME: TODO**
|
49
|
+
|
50
|
+
== Installation
|
51
|
+
|
52
|
+
Install the gem and add to the application's `Gemfile` or `gems.rb` file by executing:
|
53
|
+
|
54
|
+
[source,bash]
|
55
|
+
----
|
56
|
+
$ bundle add gvl-tracing
|
57
|
+
----
|
58
|
+
|
59
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
60
|
+
|
61
|
+
[source,bash]
|
62
|
+
----
|
63
|
+
$ gem install gvl-tracing
|
64
|
+
----
|
65
|
+
|
66
|
+
== Usage
|
67
|
+
|
68
|
+
Use `require "gvl-tracing"` to load the gem.
|
69
|
+
|
70
|
+
This gem only provides a single module (`GvlTracing`) with methods:
|
71
|
+
|
72
|
+
* `start(filename)`: Starts tracing, writing the results to the provided filename
|
73
|
+
* `stop`: Stops tracing
|
74
|
+
|
75
|
+
The resulting traces can be analyzed by going to https://ui.perfetto.dev/[Perfetto UI].
|
76
|
+
|
77
|
+
== Development
|
78
|
+
|
79
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to https://rubygems.org[rubygems.org].
|
80
|
+
|
81
|
+
== Contributing
|
82
|
+
|
83
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ivoanjo/gvl-tracing. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the https://github.com/ivoanjo/gvl-tracing/blob/master/CODE_OF_CONDUCT.adoc[code of conduct].
|
84
|
+
|
85
|
+
== Code of Conduct
|
86
|
+
|
87
|
+
Everyone interacting in the gvl-tracing project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the https://github.com/ivoanjo/gvl-tracing/blob/master/CODE_OF_CONDUCT.adoc[code of conduct].
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
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
|
+
|
32
|
+
Rake::ExtensionTask.new("gvl_tracing_native_extension")
|
33
|
+
|
34
|
+
task default: [:compile, :"standard:fix"]
|
Binary file
|
@@ -0,0 +1,18 @@
|
|
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
|
@@ -0,0 +1,35 @@
|
|
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
|
+
if ["jruby", "truffleruby"].include?(RUBY_ENGINE)
|
27
|
+
raise \
|
28
|
+
"\n#{"-" * 80}\nSorry! This gem is unsupported on #{RUBY_ENGINE}. Since it relies on a lot of guts of MRI Ruby, " \
|
29
|
+
"it's impossible to make a direct port.\n" \
|
30
|
+
"Perhaps a #{RUBY_ENGINE} equivalent could be created -- help is welcome! :)\n#{"-" * 80}"
|
31
|
+
end
|
32
|
+
|
33
|
+
require "mkmf"
|
34
|
+
|
35
|
+
create_makefile "gvl_tracing_native_extension"
|
@@ -0,0 +1,134 @@
|
|
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
|
+
#include <ruby/ruby.h>
|
27
|
+
#include <ruby/thread.h>
|
28
|
+
#include <errno.h>
|
29
|
+
#include <stdbool.h>
|
30
|
+
#include <sys/types.h>
|
31
|
+
#include <unistd.h>
|
32
|
+
|
33
|
+
static VALUE tracing_start(VALUE _self, VALUE output_path);
|
34
|
+
static VALUE tracing_stop(VALUE _self);
|
35
|
+
static double timestamp_microseconds(void);
|
36
|
+
static void render_event(const char *event_name);
|
37
|
+
static void on_event(rb_event_flag_t event, const rb_internal_thread_event_data_t *_unused1, void *_unused2);
|
38
|
+
|
39
|
+
// Global mutable state
|
40
|
+
static FILE *output_file = NULL;
|
41
|
+
static rb_internal_thread_event_hook_t *current_hook = NULL;
|
42
|
+
static double started_tracing_at_microseconds = 0;
|
43
|
+
static pid_t process_id = 0;
|
44
|
+
|
45
|
+
void Init_gvl_tracing_native_extension(void) {
|
46
|
+
VALUE gvl_tracing_module = rb_define_module("GvlTracing");
|
47
|
+
|
48
|
+
rb_define_singleton_method(gvl_tracing_module, "start", tracing_start, 1);
|
49
|
+
rb_define_singleton_method(gvl_tracing_module, "stop", tracing_stop, 0);
|
50
|
+
}
|
51
|
+
|
52
|
+
static VALUE tracing_start(VALUE _self, VALUE output_path) {
|
53
|
+
Check_Type(output_path, T_STRING);
|
54
|
+
|
55
|
+
if (output_file != NULL) rb_raise(rb_eRuntimeError, "Already started");
|
56
|
+
output_file = fopen(StringValuePtr(output_path), "w");
|
57
|
+
if (output_file == NULL) rb_syserr_fail(errno, "Failed to open GvlTracing output file");
|
58
|
+
|
59
|
+
started_tracing_at_microseconds = timestamp_microseconds();
|
60
|
+
process_id = getpid();
|
61
|
+
|
62
|
+
fprintf(output_file, "[\n");
|
63
|
+
render_event("started_tracing");
|
64
|
+
|
65
|
+
current_hook = rb_internal_thread_add_event_hook(
|
66
|
+
on_event,
|
67
|
+
(
|
68
|
+
RUBY_INTERNAL_THREAD_EVENT_READY |
|
69
|
+
RUBY_INTERNAL_THREAD_EVENT_RESUMED |
|
70
|
+
RUBY_INTERNAL_THREAD_EVENT_SUSPENDED |
|
71
|
+
RUBY_INTERNAL_THREAD_EVENT_STARTED |
|
72
|
+
RUBY_INTERNAL_THREAD_EVENT_EXITED
|
73
|
+
),
|
74
|
+
NULL
|
75
|
+
);
|
76
|
+
|
77
|
+
return Qtrue;
|
78
|
+
}
|
79
|
+
|
80
|
+
static VALUE tracing_stop(VALUE _self) {
|
81
|
+
if (output_file == NULL) rb_raise(rb_eRuntimeError, "Tracing not running");
|
82
|
+
|
83
|
+
rb_internal_thread_remove_event_hook(current_hook);
|
84
|
+
|
85
|
+
render_event("stopped_tracing");
|
86
|
+
fprintf(output_file, "]\n");
|
87
|
+
|
88
|
+
if (fclose(output_file) != 0) rb_syserr_fail(errno, "Failed to close GvlTracing output file");
|
89
|
+
|
90
|
+
output_file == NULL;
|
91
|
+
|
92
|
+
return Qtrue;
|
93
|
+
}
|
94
|
+
|
95
|
+
static double timestamp_microseconds(void) {
|
96
|
+
struct timespec current_monotonic;
|
97
|
+
if (clock_gettime(CLOCK_MONOTONIC, ¤t_monotonic) != 0) rb_syserr_fail(errno, "Failed to read CLOCK_MONOTONIC");
|
98
|
+
return (current_monotonic.tv_nsec / 1000.0) + (current_monotonic.tv_sec * 1000.0 * 1000.0);
|
99
|
+
}
|
100
|
+
|
101
|
+
// Render output using trace event format for perfetto:
|
102
|
+
// https://chromium.googlesource.com/catapult/+/refs/heads/main/docs/trace-event-format.md
|
103
|
+
static void render_event(const char *event_name) {
|
104
|
+
// Event data
|
105
|
+
double now_microseconds = timestamp_microseconds() - started_tracing_at_microseconds;
|
106
|
+
pid_t thread_id = gettid();
|
107
|
+
|
108
|
+
// Each event is converted into two events in the output: one that signals the end of the previous event
|
109
|
+
// (whatever it was), and one that signals the start of the actual event we're processing.
|
110
|
+
// Yes this is seems to be bending a bit the intention of the output format, but it seemed easier to do this way.
|
111
|
+
|
112
|
+
fprintf(output_file,
|
113
|
+
// Finish previous duration
|
114
|
+
" {\"ph\": \"E\", \"pid\": %u, \"tid\": %u, \"ts\": %f},\n" \
|
115
|
+
// Current event
|
116
|
+
" {\"ph\": \"B\", \"pid\": %u, \"tid\": %u, \"ts\": %f, \"name\": \"%s\"},\n",
|
117
|
+
// Args for first line
|
118
|
+
process_id, thread_id, now_microseconds,
|
119
|
+
// Args for second line
|
120
|
+
process_id, thread_id, now_microseconds, event_name
|
121
|
+
);
|
122
|
+
}
|
123
|
+
|
124
|
+
static void on_event(rb_event_flag_t event_id, const rb_internal_thread_event_data_t *_unused1, void *_unused2) {
|
125
|
+
const char* event_name = "bug_unknown_event";
|
126
|
+
switch (event_id) {
|
127
|
+
case RUBY_INTERNAL_THREAD_EVENT_READY: event_name = "ready"; break;
|
128
|
+
case RUBY_INTERNAL_THREAD_EVENT_RESUMED: event_name = "resumed"; break;
|
129
|
+
case RUBY_INTERNAL_THREAD_EVENT_SUSPENDED: event_name = "suspended"; break;
|
130
|
+
case RUBY_INTERNAL_THREAD_EVENT_STARTED: event_name = "started"; break;
|
131
|
+
case RUBY_INTERNAL_THREAD_EVENT_EXITED: event_name = "exited"; break;
|
132
|
+
};
|
133
|
+
render_event(event_name);
|
134
|
+
}
|
data/gems.rb
ADDED
data/gvl-tracing.gemspec
ADDED
@@ -0,0 +1,50 @@
|
|
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_relative "lib/gvl_tracing/version"
|
29
|
+
|
30
|
+
Gem::Specification.new do |spec|
|
31
|
+
spec.name = "gvl-tracing"
|
32
|
+
spec.version = GvlTracing::VERSION
|
33
|
+
spec.authors = ["Ivo Anjo"]
|
34
|
+
spec.email = ["ivo@ivoanjo.me"]
|
35
|
+
|
36
|
+
spec.summary = "Get a timeline view of Global VM Lock usage in your Ruby app"
|
37
|
+
spec.homepage = "https://github.com/ivoanjo/gvl-tracing"
|
38
|
+
spec.license = "MIT"
|
39
|
+
spec.required_ruby_version = ">= 3.2.0"
|
40
|
+
|
41
|
+
# Specify which files should be added to the gem when it is released.
|
42
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
43
|
+
spec.files = Dir.chdir(__dir__) do
|
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)})
|
46
|
+
end
|
47
|
+
end
|
48
|
+
spec.require_paths = ["lib", "ext"]
|
49
|
+
spec.extensions = ["ext/gvl_tracing_native_extension/extconf.rb"]
|
50
|
+
end
|
data/lib/gvl-tracing.rb
ADDED
@@ -0,0 +1,33 @@
|
|
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_relative "gvl_tracing/version"
|
29
|
+
|
30
|
+
require "gvl_tracing_native_extension"
|
31
|
+
|
32
|
+
module GvlTracing
|
33
|
+
end
|
@@ -0,0 +1,30 @@
|
|
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
|
+
module GvlTracing
|
29
|
+
VERSION = "0.1.0"
|
30
|
+
end
|
data/preview.png
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gvl-tracing
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ivo Anjo
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-07-10 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email:
|
15
|
+
- ivo@ivoanjo.me
|
16
|
+
executables: []
|
17
|
+
extensions:
|
18
|
+
- ext/gvl_tracing_native_extension/extconf.rb
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- ".editorconfig"
|
22
|
+
- ".standard.yml"
|
23
|
+
- CODE_OF_CONDUCT.adoc
|
24
|
+
- LICENSE
|
25
|
+
- README.adoc
|
26
|
+
- Rakefile
|
27
|
+
- examples/example1.json.gz
|
28
|
+
- examples/example1.rb
|
29
|
+
- ext/gvl_tracing_native_extension/extconf.rb
|
30
|
+
- ext/gvl_tracing_native_extension/gvl_tracing.c
|
31
|
+
- gems.rb
|
32
|
+
- gvl-tracing.gemspec
|
33
|
+
- lib/gvl-tracing.rb
|
34
|
+
- lib/gvl_tracing/version.rb
|
35
|
+
- preview.png
|
36
|
+
homepage: https://github.com/ivoanjo/gvl-tracing
|
37
|
+
licenses:
|
38
|
+
- MIT
|
39
|
+
metadata: {}
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
- ext
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 3.2.0
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
requirements: []
|
56
|
+
rubygems_version: 3.4.0.dev
|
57
|
+
signing_key:
|
58
|
+
specification_version: 4
|
59
|
+
summary: Get a timeline view of Global VM Lock usage in your Ruby app
|
60
|
+
test_files: []
|