memory-profiler 1.1.13 → 1.1.15
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
- checksums.yaml.gz.sig +0 -0
- data/ext/memory/profiler/capture.c +18 -11
- data/ext/memory/profiler/events.c +2 -8
- data/lib/memory/profiler/version.rb +1 -1
- data/readme.md +8 -8
- data/releases.md +8 -0
- data.tar.gz.sig +0 -0
- metadata +1 -1
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cce184966c5eb2b104059f419fb7f220b2bea168b5359adacc90923079332241
|
|
4
|
+
data.tar.gz: 436690f9e75f5ba72546604fd58d71efccb56d4dc8b8880feaa3b4ecab03c918
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 54d4d1e2f8d19da788e53ffa0c5e69dcaf5db708d5d1de0336bccc79c6311330a56b0c8cb605b7bb7dbc116b91b91a752cacf317d4403e5188517ddcdded12a2
|
|
7
|
+
data.tar.gz: 4994f81f0b6dd2b0c46bc3aa3e415dbc16ffb633d9fefdeafd67d10df522aaccc5003dd632a664b8eb69e476053bac5f51d0979c69c4daa97965356b1bb2ca9c
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
|
@@ -138,9 +138,9 @@ const char *event_flag_name(rb_event_flag_t event_flag) {
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
// Process a NEWOBJ event. All allocation tracking logic is here.
|
|
141
|
-
static void Memory_Profiler_Capture_process_newobj(VALUE
|
|
141
|
+
static void Memory_Profiler_Capture_process_newobj(VALUE self, VALUE klass, VALUE object) {
|
|
142
142
|
struct Memory_Profiler_Capture *capture;
|
|
143
|
-
TypedData_Get_Struct(
|
|
143
|
+
TypedData_Get_Struct(self, struct Memory_Profiler_Capture, &Memory_Profiler_Capture_type, capture);
|
|
144
144
|
|
|
145
145
|
// Pause the capture to prevent infinite loop:
|
|
146
146
|
capture->paused += 1;
|
|
@@ -168,8 +168,8 @@ static void Memory_Profiler_Capture_process_newobj(VALUE capture_value, VALUE kl
|
|
|
168
168
|
|
|
169
169
|
allocations = Memory_Profiler_Allocations_wrap(record);
|
|
170
170
|
st_insert(capture->tracked_classes, (st_data_t)klass, (st_data_t)allocations);
|
|
171
|
-
RB_OBJ_WRITTEN(
|
|
172
|
-
RB_OBJ_WRITTEN(
|
|
171
|
+
RB_OBJ_WRITTEN(self, Qnil, klass);
|
|
172
|
+
RB_OBJ_WRITTEN(self, Qnil, allocations);
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
// Only store state if there's a callback
|
|
@@ -298,10 +298,19 @@ static void Memory_Profiler_Capture_event_callback(VALUE data, void *ptr) {
|
|
|
298
298
|
VALUE klass = rb_class_of(object);
|
|
299
299
|
if (!klass) return;
|
|
300
300
|
|
|
301
|
+
if (DEBUG) {
|
|
302
|
+
const char *klass_name = "(ignored)";
|
|
303
|
+
if (event_flag == RUBY_INTERNAL_EVENT_NEWOBJ) {
|
|
304
|
+
klass_name = rb_class2name(klass);
|
|
305
|
+
}
|
|
306
|
+
fprintf(stderr, "Memory_Profiler_Capture_event_callback: object=%p, event_flag=%s, klass=%s\n", (void*)object, event_flag_name(event_flag), klass_name);
|
|
307
|
+
}
|
|
308
|
+
|
|
301
309
|
if (event_flag == RUBY_INTERNAL_EVENT_NEWOBJ) {
|
|
302
310
|
// Skip NEWOBJ if disabled (during callback) to prevent infinite recursion
|
|
303
311
|
if (capture->paused) return;
|
|
304
312
|
|
|
313
|
+
// Check if class is already freed (T_NONE). This can happen when:
|
|
305
314
|
// It's safe to unconditionally call here:
|
|
306
315
|
object = rb_obj_id(object);
|
|
307
316
|
|
|
@@ -309,6 +318,10 @@ static void Memory_Profiler_Capture_event_callback(VALUE data, void *ptr) {
|
|
|
309
318
|
} else if (event_flag == RUBY_INTERNAL_EVENT_FREEOBJ) {
|
|
310
319
|
// We only care about objects that have been seen before (i.e. have an object ID):
|
|
311
320
|
if (RB_FL_TEST(object, FL_SEEN_OBJ_ID)) {
|
|
321
|
+
// For freeobj, we only care about klasses that we are tracking.
|
|
322
|
+
// This prevents us from enqueuing klass objects that might be freed.
|
|
323
|
+
if (!st_lookup(capture->tracked_classes, (st_data_t)klass, NULL)) return;
|
|
324
|
+
|
|
312
325
|
// It's only safe to call here if the object already has an object ID.
|
|
313
326
|
object = rb_obj_id(object);
|
|
314
327
|
|
|
@@ -417,7 +430,7 @@ static VALUE Memory_Profiler_Capture_track(int argc, VALUE *argv, VALUE self) {
|
|
|
417
430
|
RB_OBJ_WRITE(self, &record->callback, callback);
|
|
418
431
|
} else {
|
|
419
432
|
struct Memory_Profiler_Capture_Allocations *record = ALLOC(struct Memory_Profiler_Capture_Allocations);
|
|
420
|
-
record->callback
|
|
433
|
+
RB_OBJ_WRITE(self, &record->callback, callback);
|
|
421
434
|
record->new_count = 0;
|
|
422
435
|
record->free_count = 0;
|
|
423
436
|
record->states = st_init_numtable();
|
|
@@ -426,14 +439,8 @@ static VALUE Memory_Profiler_Capture_track(int argc, VALUE *argv, VALUE self) {
|
|
|
426
439
|
allocations = Memory_Profiler_Allocations_wrap(record);
|
|
427
440
|
|
|
428
441
|
st_insert(capture->tracked_classes, (st_data_t)klass, (st_data_t)allocations);
|
|
429
|
-
// Notify GC about the class VALUE stored as key in the table
|
|
430
442
|
RB_OBJ_WRITTEN(self, Qnil, klass);
|
|
431
|
-
// Notify GC about the allocations VALUE stored as value in the table
|
|
432
443
|
RB_OBJ_WRITTEN(self, Qnil, allocations);
|
|
433
|
-
// Now inform GC about the callback reference
|
|
434
|
-
if (!NIL_P(callback)) {
|
|
435
|
-
RB_OBJ_WRITTEN(self, Qnil, callback);
|
|
436
|
-
}
|
|
437
444
|
}
|
|
438
445
|
|
|
439
446
|
return allocations;
|
|
@@ -31,6 +31,7 @@ static void Memory_Profiler_Events_mark(void *ptr);
|
|
|
31
31
|
static void Memory_Profiler_Events_compact(void *ptr);
|
|
32
32
|
static void Memory_Profiler_Events_free(void *ptr);
|
|
33
33
|
static size_t Memory_Profiler_Events_memsize(const void *ptr);
|
|
34
|
+
static const char *Memory_Profiler_Event_Type_name(enum Memory_Profiler_Event_Type type);
|
|
34
35
|
|
|
35
36
|
// TypedData definition for Events.
|
|
36
37
|
static const rb_data_type_t Memory_Profiler_Events_type = {
|
|
@@ -102,15 +103,9 @@ static void Memory_Profiler_Events_mark_queue(struct Memory_Profiler_Queue *queu
|
|
|
102
103
|
// Skip already-processed events if requested:
|
|
103
104
|
if (skip_none && event->type == MEMORY_PROFILER_EVENT_TYPE_NONE) continue;
|
|
104
105
|
|
|
105
|
-
// Mark the Capture instance and class:
|
|
106
106
|
rb_gc_mark_movable(event->capture);
|
|
107
107
|
rb_gc_mark_movable(event->klass);
|
|
108
|
-
|
|
109
|
-
// For NEWOBJ: mark the object to keep it alive until processor runs
|
|
110
|
-
// For FREEOBJ: DON'T mark (object is being freed)
|
|
111
|
-
if (event->type == MEMORY_PROFILER_EVENT_TYPE_NEWOBJ) {
|
|
112
|
-
rb_gc_mark_movable(event->object);
|
|
113
|
-
}
|
|
108
|
+
rb_gc_mark_movable(event->object);
|
|
114
109
|
}
|
|
115
110
|
}
|
|
116
111
|
|
|
@@ -133,7 +128,6 @@ static void Memory_Profiler_Events_compact_queue(struct Memory_Profiler_Queue *q
|
|
|
133
128
|
// Skip already-processed events if requested:
|
|
134
129
|
if (skip_none && event->type == MEMORY_PROFILER_EVENT_TYPE_NONE) continue;
|
|
135
130
|
|
|
136
|
-
// Update all VALUEs if they moved during compaction:
|
|
137
131
|
event->capture = rb_gc_location(event->capture);
|
|
138
132
|
event->klass = rb_gc_location(event->klass);
|
|
139
133
|
event->object = rb_gc_location(event->object);
|
data/readme.md
CHANGED
|
@@ -22,6 +22,14 @@ Please see the [project documentation](https://socketry.github.io/memory-profile
|
|
|
22
22
|
|
|
23
23
|
Please see the [project releases](https://socketry.github.io/memory-profiler/releases/index) for all releases.
|
|
24
24
|
|
|
25
|
+
### v1.1.15
|
|
26
|
+
|
|
27
|
+
- Ignore `freeobj` for classes that are not being tracked.
|
|
28
|
+
|
|
29
|
+
### v1.1.14
|
|
30
|
+
|
|
31
|
+
- Ignore `freeobj` events for objects with anonymous classes that are not tracked (and thus become `T_NONE`).
|
|
32
|
+
|
|
25
33
|
### v1.1.13
|
|
26
34
|
|
|
27
35
|
- Fix sampler loop interval handling.
|
|
@@ -62,14 +70,6 @@ Please see the [project releases](https://socketry.github.io/memory-profiler/rel
|
|
|
62
70
|
- Better state handling and object increment/decrement counting.
|
|
63
71
|
- Better call tree handling - including support for `prune!`.
|
|
64
72
|
|
|
65
|
-
### v1.1.5
|
|
66
|
-
|
|
67
|
-
- Use queue for `newobj` too to avoid invoking user code during object allocation.
|
|
68
|
-
|
|
69
|
-
### v1.1.2
|
|
70
|
-
|
|
71
|
-
- Fix handling of GC compaction (I hope).
|
|
72
|
-
|
|
73
73
|
## Contributing
|
|
74
74
|
|
|
75
75
|
We welcome contributions to this project.
|
data/releases.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Releases
|
|
2
2
|
|
|
3
|
+
## v1.1.15
|
|
4
|
+
|
|
5
|
+
- Ignore `freeobj` for classes that are not being tracked.
|
|
6
|
+
|
|
7
|
+
## v1.1.14
|
|
8
|
+
|
|
9
|
+
- Ignore `freeobj` events for objects with anonymous classes that are not tracked (and thus become `T_NONE`).
|
|
10
|
+
|
|
3
11
|
## v1.1.13
|
|
4
12
|
|
|
5
13
|
- Fix sampler loop interval handling.
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
metadata.gz.sig
CHANGED
|
Binary file
|