memory-profiler 1.1.13 → 1.1.14
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 +28 -11
- data/ext/memory/profiler/events.c +2 -8
- data/lib/memory/profiler/version.rb +1 -1
- data/readme.md +4 -4
- data/releases.md +4 -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: c26d5bc8b4215de3776e42ec9cd8daaf54a3cba9d55449f6b570ba7ee5ef9c91
|
|
4
|
+
data.tar.gz: 6668320402b35e3633eff016bd79b34c6b69952cb03120fc7f04886782bacfe3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 68404ae44a442584084727cc854ed81abc36964c5621b93361cde70c6ae80f71ad21c7a45caf049c5906846cec8dff23ccbddb2e021eedf137e8ba7d57c78363
|
|
7
|
+
data.tar.gz: 406d8caac175e30907d752cec211d066a8c7ed5bf260c4e4eba6304f73b60d7c47be6d68d8b6cc4e738cb8fe19ebadeea0f251c7b2df888923b86abdaae2867e
|
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,6 +298,29 @@ 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
|
+
// Check if class is already freed (T_NONE). This can happen when:
|
|
302
|
+
// 1. Object was allocated before capture started (no NEWOBJ event queued).
|
|
303
|
+
// 2. Anonymous class (Class.new) was freed before its instances.
|
|
304
|
+
//
|
|
305
|
+
// If the class is T_NONE, it means:
|
|
306
|
+
// - It's NOT in tracked_classes (would retain it via GC mark callback).
|
|
307
|
+
// - It's NOT in any pending NEWOBJ event (would retain it via event queue marking).
|
|
308
|
+
//
|
|
309
|
+
// Therefore process_freeobj() would skip this event anyway (class lookup fails at line 200).
|
|
310
|
+
// We must skip enqueueing to avoid attempting to mark a T_NONE object during GC,
|
|
311
|
+
// which can cause: [BUG] try to mark T_NONE object.
|
|
312
|
+
if (rb_type(klass) == T_NONE) {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (DEBUG) {
|
|
317
|
+
const char *klass_name = "(ignored)";
|
|
318
|
+
if (event_flag == RUBY_INTERNAL_EVENT_NEWOBJ) {
|
|
319
|
+
klass_name = rb_class2name(klass);
|
|
320
|
+
}
|
|
321
|
+
fprintf(stderr, "Memory_Profiler_Capture_event_callback: object=%p, event_flag=%s, klass=%s\n", (void*)object, event_flag_name(event_flag), klass_name);
|
|
322
|
+
}
|
|
323
|
+
|
|
301
324
|
if (event_flag == RUBY_INTERNAL_EVENT_NEWOBJ) {
|
|
302
325
|
// Skip NEWOBJ if disabled (during callback) to prevent infinite recursion
|
|
303
326
|
if (capture->paused) return;
|
|
@@ -417,7 +440,7 @@ static VALUE Memory_Profiler_Capture_track(int argc, VALUE *argv, VALUE self) {
|
|
|
417
440
|
RB_OBJ_WRITE(self, &record->callback, callback);
|
|
418
441
|
} else {
|
|
419
442
|
struct Memory_Profiler_Capture_Allocations *record = ALLOC(struct Memory_Profiler_Capture_Allocations);
|
|
420
|
-
record->callback
|
|
443
|
+
RB_OBJ_WRITE(self, &record->callback, callback);
|
|
421
444
|
record->new_count = 0;
|
|
422
445
|
record->free_count = 0;
|
|
423
446
|
record->states = st_init_numtable();
|
|
@@ -426,14 +449,8 @@ static VALUE Memory_Profiler_Capture_track(int argc, VALUE *argv, VALUE self) {
|
|
|
426
449
|
allocations = Memory_Profiler_Allocations_wrap(record);
|
|
427
450
|
|
|
428
451
|
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
452
|
RB_OBJ_WRITTEN(self, Qnil, klass);
|
|
431
|
-
// Notify GC about the allocations VALUE stored as value in the table
|
|
432
453
|
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
454
|
}
|
|
438
455
|
|
|
439
456
|
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,10 @@ 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.14
|
|
26
|
+
|
|
27
|
+
- Ignore `freeobj` events for objects with anonymous classes that are not tracked (and thus become `T_NONE`).
|
|
28
|
+
|
|
25
29
|
### v1.1.13
|
|
26
30
|
|
|
27
31
|
- Fix sampler loop interval handling.
|
|
@@ -66,10 +70,6 @@ Please see the [project releases](https://socketry.github.io/memory-profiler/rel
|
|
|
66
70
|
|
|
67
71
|
- Use queue for `newobj` too to avoid invoking user code during object allocation.
|
|
68
72
|
|
|
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
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
metadata.gz.sig
CHANGED
|
Binary file
|