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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2cc3a03e3b76e232615954217c88c54d2077da267793f79c9b5dc5d8463398f6
4
- data.tar.gz: 29466a48c28857d7093156c80072dc3cba66420275b307cb2fea64102ece2624
3
+ metadata.gz: cce184966c5eb2b104059f419fb7f220b2bea168b5359adacc90923079332241
4
+ data.tar.gz: 436690f9e75f5ba72546604fd58d71efccb56d4dc8b8880feaa3b4ecab03c918
5
5
  SHA512:
6
- metadata.gz: 9171990674d31df2af4daa7ed082b696ce1a093cb8f83ba6bab1d82ed1ef2704bb3cb4aef48758db7ba6b815e8729483d8b2124f3f687a77f3029400e1e3bb7b
7
- data.tar.gz: 4f4845133c13fe67caa4641df912280983d05f4c6e0fca324b0827f0ffbbd040710670e9d3cd1ef6e6ab7d61bbbe22334f89ffbf4286652f4d4e361891f2dfb5
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 capture_value, VALUE klass, VALUE object) {
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(capture_value, struct Memory_Profiler_Capture, &Memory_Profiler_Capture_type, capture);
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(capture_value, Qnil, klass);
172
- RB_OBJ_WRITTEN(capture_value, Qnil, allocations);
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 = callback; // Initial assignment, no write barrier needed
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);
@@ -7,7 +7,7 @@
7
7
  module Memory
8
8
  # @namespace
9
9
  module Profiler
10
- VERSION = "1.1.13"
10
+ VERSION = "1.1.15"
11
11
  end
12
12
  end
13
13
 
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
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: memory-profiler
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.13
4
+ version: 1.1.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
metadata.gz.sig CHANGED
Binary file