lowlevel-toolkit 0.1.0 → 0.2.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/ext/lowlevel_toolkit_native_extension/last_allocation_at.c +2 -2
- data/ext/lowlevel_toolkit_native_extension/print_gc_timing.c +3 -1
- data/ext/lowlevel_toolkit_native_extension/release_gvl_profiler.c +4 -5
- data/ext/lowlevel_toolkit_native_extension/track_wants_gvl.c +2 -0
- data/ext/lowlevel_toolkit_native_extension/who_called_me.c +4 -4
- data/lib/lowlevel_toolkit/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70c3208f01e4a74022c7a9863ef211932af9a4a68b488e4c48617330d669ee19
|
4
|
+
data.tar.gz: 9752724445dc3214669da9018c1f24d553356c54534787827f740f24c37aada8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2645f4993532e8fdc77e01e6f0e055225f3151c46f05b540522f7a2b773277dc29f5ada32589a5f2a3b47a0d7b1f02fb1618e620f9a0b406ad483393e0f1ebee
|
7
|
+
data.tar.gz: 8794ad2fe4f38b9b66dec535da028144f43144f62ed9d116633b0673af1067a8f5458c80123907b8f5f8f4139e4382749cfb216f3845d968dc70be1482d0ac9e
|
@@ -9,7 +9,7 @@ static VALUE stack = Qnil;
|
|
9
9
|
static void on_newobj_event(VALUE tpval, RB_UNUSED_VAR(void *_)) {
|
10
10
|
if (stack == Qnil ||
|
11
11
|
rb_objspace_internal_object_p(rb_tracearg_object(rb_tracearg_from_tracepoint(tpval)))) return;
|
12
|
-
VALUE buffer[MAX_DEPTH];
|
12
|
+
VALUE buffer[MAX_DEPTH]; // Temporary buffer for calling API
|
13
13
|
int depth = rb_profile_frames(0, MAX_DEPTH, buffer, NULL);
|
14
14
|
rb_ary_clear(stack);
|
15
15
|
for (int i = 0; i < depth; i++) rb_ary_push(stack, buffer[i]);
|
@@ -29,7 +29,7 @@ static VALUE last_allocation_at(RB_UNUSED_VAR(VALUE _)) {
|
|
29
29
|
for (int i = 0; i < RARRAY_LEN(raw_stack); i++) {
|
30
30
|
VALUE entry = rb_ary_entry(raw_stack, i);
|
31
31
|
VALUE file = rb_profile_frame_path(entry);
|
32
|
-
if (file != Qnil) rb_ary_push(result, rb_ary_new_from_args(2, file,
|
32
|
+
if (file != Qnil) rb_ary_push(result, rb_ary_new_from_args(2, file, rb_profile_frame_label(entry)));
|
33
33
|
}
|
34
34
|
stack = raw_stack; // Resume recording again
|
35
35
|
return result;
|
@@ -7,6 +7,8 @@ static uint64_t get_monotonic_time_ns(void) {
|
|
7
7
|
return (uint64_t) ts.tv_sec * 1000000000ULL + (uint64_t) ts.tv_nsec;
|
8
8
|
}
|
9
9
|
|
10
|
+
static inline double ns_to_ms(uint64_t ns) { return ns / 1000000.0; }
|
11
|
+
|
10
12
|
static void on_gc_event(VALUE tpval, RB_UNUSED_VAR(void *_)) {
|
11
13
|
static uint64_t gc_start_time = 0;
|
12
14
|
rb_event_flag_t event = rb_tracearg_event_flag(rb_tracearg_from_tracepoint(tpval));
|
@@ -14,7 +16,7 @@ static void on_gc_event(VALUE tpval, RB_UNUSED_VAR(void *_)) {
|
|
14
16
|
if (event == RUBY_INTERNAL_EVENT_GC_ENTER) {
|
15
17
|
gc_start_time = get_monotonic_time_ns();
|
16
18
|
} else if (event == RUBY_INTERNAL_EVENT_GC_EXIT) {
|
17
|
-
fprintf(stdout, "GC worked for %.2f ms\n", (
|
19
|
+
fprintf(stdout, "GC worked for %.2f ms\n", ns_to_ms(get_monotonic_time_ns() - gc_start_time));
|
18
20
|
}
|
19
21
|
}
|
20
22
|
|
@@ -26,17 +26,16 @@ static void on_thread_event(rb_event_flag_t event_id, const rb_internal_thread_e
|
|
26
26
|
|
27
27
|
// If we wanted to delay processing the backtrace, we could switch to rb_profile_frames() here
|
28
28
|
VALUE frames = rb_make_backtrace();
|
29
|
-
VALUE result = (VALUE) data;
|
30
29
|
|
31
|
-
VALUE stats = rb_hash_aref(
|
30
|
+
VALUE stats = rb_hash_aref((VALUE) data, frames);
|
32
31
|
if (stats == Qnil) {
|
33
32
|
stats = rb_ary_new_from_args(2, INT2FIX(0), INT2FIX(0));
|
34
|
-
rb_hash_aset(
|
33
|
+
rb_hash_aset((VALUE) data, frames, stats);
|
35
34
|
}
|
36
35
|
|
37
36
|
uint64_t time_spent = get_monotonic_time_ns() - release_gvl_at;
|
38
|
-
rb_ary_store(stats, 0, ULL2NUM(NUM2ULL(rb_ary_entry(stats, 0)) + time_spent));
|
39
|
-
rb_ary_store(stats, 1, ULL2NUM(NUM2ULL(rb_ary_entry(stats, 1)) + 1));
|
37
|
+
rb_ary_store(stats, 0, ULL2NUM(NUM2ULL(rb_ary_entry(stats, 0)) + time_spent)); // Time
|
38
|
+
rb_ary_store(stats, 1, ULL2NUM(NUM2ULL(rb_ary_entry(stats, 1)) + 1)); // Counts
|
40
39
|
}
|
41
40
|
}
|
42
41
|
|
@@ -14,6 +14,8 @@ static int total_wants_key;
|
|
14
14
|
static void on_thread_event(rb_event_flag_t event_id, const rb_internal_thread_event_data_t *event_data, void *data) {
|
15
15
|
VALUE thread = event_data->thread;
|
16
16
|
if (event_id == RUBY_INTERNAL_THREAD_EVENT_STARTED) {
|
17
|
+
// BUG: This is not thread safe... but works sometimes
|
18
|
+
// TODO: Replace with safe data structure
|
17
19
|
rb_ary_push((VALUE) data, thread);
|
18
20
|
} else if (event_id == RUBY_INTERNAL_THREAD_EVENT_READY) {
|
19
21
|
rb_internal_thread_specific_set(thread, wants_gvl_at_key, (void *) get_monotonic_time_ns());
|
@@ -1,11 +1,11 @@
|
|
1
1
|
#include <ruby/ruby.h>
|
2
2
|
#include <ruby/debug.h>
|
3
3
|
|
4
|
-
static VALUE callback(const rb_debug_inspector_t *dbg_context, void *
|
5
|
-
|
6
|
-
return return_self ?
|
4
|
+
static VALUE callback(const rb_debug_inspector_t *dbg_context, void *return_self) {
|
5
|
+
return (return_self != NULL) ?
|
7
6
|
// Depth: 0 -> us; 1 -> caller; 2 -> caller of caller
|
8
|
-
rb_debug_inspector_frame_self_get(dbg_context, 2) :
|
7
|
+
rb_debug_inspector_frame_self_get(dbg_context, 2) :
|
8
|
+
rb_debug_inspector_frame_binding_get(dbg_context, 2);
|
9
9
|
}
|
10
10
|
|
11
11
|
static VALUE who_called_me(RB_UNUSED_VAR(VALUE _)) { return rb_debug_inspector_open(callback, (void *) !NULL); }
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lowlevel-toolkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivo Anjo
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-04-
|
10
|
+
date: 2025-04-15 00:00:00.000000000 Z
|
11
11
|
dependencies: []
|
12
12
|
email:
|
13
13
|
- ivo@ivoanjo.me
|