memory-profiler 1.3.0 → 1.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f059f309b7c1fd6fcffd119a0f6d40e8d4480783e2955ad3fc054fa280015f9d
4
- data.tar.gz: e3c1ddd9afd7240b3bf727f6b6219b2bcb2e164c8e9c1c245ac4163684b180b8
3
+ metadata.gz: cc8f56ebed50c8d591a542d81163ea09246a2661f4bd32124ea8d524f67ee940
4
+ data.tar.gz: 236d1bfdb3599fe908435f62a405ed6d0e21addc9cb1cac246b32e4513e55aac
5
5
  SHA512:
6
- metadata.gz: 2bd209fd9a3c9f3116bf0c76b405c1fed1580f5412292646749539f73eb5e2b7334e2267a5bbd43fbc4c13fa7c8385422e32f369779e62f022966e56108a46c3
7
- data.tar.gz: 6e38c7368db453b2476a0084bbcdca8c60df5d0c51d2395df5e23c18a2b4f49f3bbbd64f5e562af2a02e91a0cd73b6cc129000eb80f75e485afbfe3b9d769ff2
6
+ metadata.gz: 42644bc37643d89de3e2fad38bc58fb374e5dbd213be7c1c47df4bfcf2f1ad6ffe579ae33933e69c44c8b844ff163b19511cbbade95aedd8767858deea8cb038
7
+ data.tar.gz: e18bffb078694246200f30b0d3199940e644eea56826dd86aef79787dfe79a96fddee09625f62c6fec88883c8ac3ae425fab38e838cded33ce98f7ae30903c70
checksums.yaml.gz.sig CHANGED
Binary file
@@ -2,75 +2,28 @@
2
2
  // Copyright, 2025, by Samuel Williams.
3
3
 
4
4
  #include "allocations.h"
5
-
6
- #include "ruby.h"
7
- #include "ruby/debug.h"
8
- #include "ruby/st.h"
5
+ #include "events.h"
6
+ #include <ruby/debug.h>
9
7
  #include <stdio.h>
10
8
 
11
9
  static VALUE Memory_Profiler_Allocations = Qnil;
12
10
 
13
- // Helper to mark states table (object => state)
14
- static int Memory_Profiler_Allocations_states_mark(st_data_t key, st_data_t value, st_data_t arg) {
15
- // We don't want the key to move - we can't rehash the table if it does.
16
- rb_gc_mark((VALUE)key);
17
-
18
- VALUE state = (VALUE)value;
19
- rb_gc_mark_movable(state);
20
- return ST_CONTINUE;
21
- }
22
-
23
- // Foreach callback for st_foreach_with_replace (iteration logic)
24
- static int Memory_Profiler_Allocations_states_foreach(st_data_t key, st_data_t value, st_data_t argp, int error) {
25
- // Return ST_REPLACE to trigger the replace callback for each entry
26
- return ST_REPLACE;
27
- }
28
-
29
- // Replace callback for st_foreach_with_replace to update states during compaction
30
- static int Memory_Profiler_Allocations_states_compact(st_data_t *key, st_data_t *value, st_data_t data, int existing) {
31
- *value = (st_data_t)rb_gc_location((VALUE)*value);
32
-
33
- return ST_CONTINUE;
34
- }
35
-
36
11
  static void Memory_Profiler_Allocations_mark(void *ptr) {
37
12
  struct Memory_Profiler_Capture_Allocations *record = ptr;
38
13
 
39
- if (!record) {
40
- return;
41
- }
42
-
43
14
  rb_gc_mark_movable(record->callback);
44
-
45
- // Mark states table if it exists
46
- if (record->states) {
47
- st_foreach(record->states, Memory_Profiler_Allocations_states_mark, 0);
48
- }
49
15
  }
50
16
 
51
17
  static void Memory_Profiler_Allocations_free(void *ptr) {
52
18
  struct Memory_Profiler_Capture_Allocations *record = ptr;
53
19
 
54
- if (record->states) {
55
- st_free_table(record->states);
56
- }
57
-
58
20
  xfree(record);
59
21
  }
60
22
 
61
- // GC compact function for Allocations
62
23
  static void Memory_Profiler_Allocations_compact(void *ptr) {
63
24
  struct Memory_Profiler_Capture_Allocations *record = ptr;
64
25
 
65
- // Update callback if it moved
66
26
  record->callback = rb_gc_location(record->callback);
67
-
68
- // Update states table if it exists
69
- if (record->states && record->states->num_entries > 0) {
70
- if (st_foreach_with_replace(record->states, Memory_Profiler_Allocations_states_foreach, Memory_Profiler_Allocations_states_compact, 0)) {
71
- rb_raise(rb_eRuntimeError, "states modified during GC compaction");
72
- }
73
- }
74
27
  }
75
28
 
76
29
  static const rb_data_type_t Memory_Profiler_Allocations_type = {
@@ -83,25 +36,21 @@ static const rb_data_type_t Memory_Profiler_Allocations_type = {
83
36
  0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
84
37
  };
85
38
 
86
- // Wrap an allocations record
87
39
  VALUE Memory_Profiler_Allocations_wrap(struct Memory_Profiler_Capture_Allocations *record) {
88
40
  return TypedData_Wrap_Struct(Memory_Profiler_Allocations, &Memory_Profiler_Allocations_type, record);
89
41
  }
90
42
 
91
- // Get allocations record from wrapper
92
43
  struct Memory_Profiler_Capture_Allocations* Memory_Profiler_Allocations_get(VALUE self) {
93
44
  struct Memory_Profiler_Capture_Allocations *record;
94
45
  TypedData_Get_Struct(self, struct Memory_Profiler_Capture_Allocations, &Memory_Profiler_Allocations_type, record);
95
46
  return record;
96
47
  }
97
48
 
98
- // Allocations#new_count
99
49
  static VALUE Memory_Profiler_Allocations_new_count(VALUE self) {
100
50
  struct Memory_Profiler_Capture_Allocations *record = Memory_Profiler_Allocations_get(self);
101
51
  return SIZET2NUM(record->new_count);
102
52
  }
103
53
 
104
- // Allocations#free_count
105
54
  static VALUE Memory_Profiler_Allocations_free_count(VALUE self) {
106
55
  struct Memory_Profiler_Capture_Allocations *record = Memory_Profiler_Allocations_get(self);
107
56
  return SIZET2NUM(record->free_count);
@@ -110,46 +59,36 @@ static VALUE Memory_Profiler_Allocations_free_count(VALUE self) {
110
59
  // Allocations#retained_count
111
60
  static VALUE Memory_Profiler_Allocations_retained_count(VALUE self) {
112
61
  struct Memory_Profiler_Capture_Allocations *record = Memory_Profiler_Allocations_get(self);
113
- // Handle underflow when free_count > new_count
62
+
63
+ // Handle underflow when free_count > new_count:
114
64
  size_t retained = record->free_count > record->new_count ? 0 : record->new_count - record->free_count;
65
+
115
66
  return SIZET2NUM(retained);
116
67
  }
117
68
 
118
- // Allocations#track { |klass| ... }
119
69
  static VALUE Memory_Profiler_Allocations_track(int argc, VALUE *argv, VALUE self) {
120
70
  struct Memory_Profiler_Capture_Allocations *record = Memory_Profiler_Allocations_get(self);
121
71
 
122
72
  VALUE callback;
123
73
  rb_scan_args(argc, argv, "&", &callback);
124
74
 
125
- // Use write barrier - self (Allocations wrapper) keeps Capture alive, which keeps callback alive
126
75
  RB_OBJ_WRITE(self, &record->callback, callback);
127
76
 
128
77
  return self;
129
78
  }
130
79
 
131
- // Clear/reset allocation counts and state for a record
132
80
  void Memory_Profiler_Allocations_clear(VALUE allocations) {
133
81
  struct Memory_Profiler_Capture_Allocations *record = Memory_Profiler_Allocations_get(allocations);
134
- record->new_count = 0; // Reset allocation count
135
- record->free_count = 0; // Reset free count
136
- RB_OBJ_WRITE(allocations, &record->callback, Qnil); // Clear callback with write barrier
137
-
138
- // Clear states - either clear the table or reinitialize
139
- if (record->states) {
140
- st_clear(record->states);
141
- } else {
142
- record->states = st_init_numtable();
143
- }
82
+ record->new_count = 0;
83
+ record->free_count = 0;
84
+ RB_OBJ_WRITE(allocations, &record->callback, Qnil);
144
85
  }
145
86
 
146
- // Allocate a new Allocations object (for testing)
147
87
  static VALUE Memory_Profiler_Allocations_allocate(VALUE klass) {
148
88
  struct Memory_Profiler_Capture_Allocations *record = ALLOC(struct Memory_Profiler_Capture_Allocations);
149
89
  record->callback = Qnil;
150
90
  record->new_count = 0;
151
91
  record->free_count = 0;
152
- record->states = st_init_numtable();
153
92
 
154
93
  return Memory_Profiler_Allocations_wrap(record);
155
94
  }
@@ -165,5 +104,5 @@ void Init_Memory_Profiler_Allocations(VALUE Memory_Profiler)
165
104
  rb_define_method(Memory_Profiler_Allocations, "new_count", Memory_Profiler_Allocations_new_count, 0);
166
105
  rb_define_method(Memory_Profiler_Allocations, "free_count", Memory_Profiler_Allocations_free_count, 0);
167
106
  rb_define_method(Memory_Profiler_Allocations, "retained_count", Memory_Profiler_Allocations_retained_count, 0);
168
- rb_define_method(Memory_Profiler_Allocations, "track", Memory_Profiler_Allocations_track, -1); // -1 to accept block
107
+ rb_define_method(Memory_Profiler_Allocations, "track", Memory_Profiler_Allocations_track, -1);
169
108
  }
@@ -3,8 +3,8 @@
3
3
 
4
4
  #pragma once
5
5
 
6
- #include "ruby.h"
7
- #include "ruby/st.h"
6
+ #include <ruby.h>
7
+ #include <ruby/st.h>
8
8
 
9
9
  // Per-class allocation tracking record:
10
10
  struct Memory_Profiler_Capture_Allocations {
@@ -16,10 +16,6 @@ struct Memory_Profiler_Capture_Allocations {
16
16
  // // Total frees seen since tracking started.
17
17
  size_t free_count;
18
18
  // Live count = new_count - free_count.
19
-
20
- // Map object (VALUE) => state (VALUE).
21
- // Object keys need compaction updates when they move.
22
- st_table *states;
23
19
  };
24
20
 
25
21
  // Wrap an allocations record in a VALUE.
@@ -28,7 +24,7 @@ VALUE Memory_Profiler_Allocations_wrap(struct Memory_Profiler_Capture_Allocation
28
24
  // Get allocations record from wrapper VALUE.
29
25
  struct Memory_Profiler_Capture_Allocations* Memory_Profiler_Allocations_get(VALUE self);
30
26
 
31
- // Clear/reset allocation counts and state for a record.
27
+ // Clear/reset allocation counts for a record.
32
28
  void Memory_Profiler_Allocations_clear(VALUE allocations);
33
29
 
34
30
  // Initialize the Allocations class.