allocations 1.0.4 → 1.0.5

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
  SHA1:
3
- metadata.gz: 9f684c28383cf0174b1410aacedd436771f14603
4
- data.tar.gz: c8cb8d726e5edbe6a81005c65ffce812a4688c6a
3
+ metadata.gz: a46f508510123c761b991e64889ac068ed815bd8
4
+ data.tar.gz: d68c81c787976c85a8887cc7bdab6968d4edf279
5
5
  SHA512:
6
- metadata.gz: f17e896bcb848cbbcc59cf5bee39ba3baf318eb995bacf90df28b654143b07a2670a1c55f6e692ac7475f67515783987b56614af01804e70799dc4f6e926f45c
7
- data.tar.gz: 325c979378375a49ac0d233abc3cd1bea91b903765dcd9fe7c66a34e52e9b1dd7b01e08fb675179c814f830409cab05d5f4fad51fb7bae9dfddff9758df59239
6
+ metadata.gz: 2d3b904496f79e974224f08a32ccd5063f15246947a9f74d29278b1205c2c6329b00302865534561dedf666601622ab994b5559b8dd7536a12b31e7ba8142107
7
+ data.tar.gz: c2ea1a53ac53a20e4b95e59d7ace5ef05890b23885a7af8fd8f9a85a923d499c9c8bccf5cc7d0a609fbddb82b5b325d1cbbf4f598582465927f1d4e62902f2d6
@@ -1,12 +1,14 @@
1
1
  #include "liballocations.h"
2
2
 
3
- st_table *object_counts;
4
-
5
3
  VALUE allocation_tracer;
6
4
  VALUE free_tracer;
5
+ VALUE state_const;
7
6
 
8
7
  ID id_enabled;
9
8
 
9
+ #define IS_SINGLETON(klass) \
10
+ RB_TYPE_P(klass, T_CLASS) && FL_TEST(klass, FL_SINGLETON)
11
+
10
12
  /**
11
13
  * Called whenever a new Ruby object is allocated.
12
14
  */
@@ -15,16 +17,23 @@ void newobj_callback(VALUE tracepoint, void* data) {
15
17
 
16
18
  st_data_t count = 0;
17
19
 
18
- VALUE obj = rb_tracearg_object(trace_arg);
19
- VALUE klass = RBASIC_CLASS(obj);
20
+ AllocationState *state = allocation_state_get_struct(state_const);
21
+
22
+ VALUE klass = rb_tracearg_defined_class(trace_arg);
20
23
 
21
24
  /* These aren't actually allocated so there's no point in tracking them. */
22
25
  if ( klass == Qtrue || klass == Qfalse || klass == Qnil ) {
23
26
  return;
24
27
  }
25
28
 
26
- st_lookup(object_counts, (st_data_t) klass, &count);
27
- st_insert(object_counts, (st_data_t) klass, count + 1);
29
+ // We don't care about sigleton classes since only one of them exists at a
30
+ // time. The logic here is stolen from MRI's implementation of
31
+ // Class#singleton_class? as MRI sadly provides no public C function for
32
+ // this method.
33
+ if ( IS_SINGLETON(klass) ) return;
34
+
35
+ st_lookup(state->object_counts, (st_data_t) klass, &count);
36
+ st_insert(state->object_counts, (st_data_t) klass, count + 1);
28
37
  }
29
38
 
30
39
  /**
@@ -34,20 +43,22 @@ void newobj_callback(VALUE tracepoint, void* data) {
34
43
  * segfault.
35
44
  */
36
45
  void freeobj_callback(VALUE tracepoint, void* data) {
46
+ st_data_t count;
47
+
37
48
  rb_trace_arg_t *trace_arg = rb_tracearg_from_tracepoint(tracepoint);
49
+ AllocationState *state = allocation_state_get_struct(state_const);
38
50
 
39
- st_data_t count;
51
+ VALUE klass = rb_tracearg_defined_class(trace_arg);
40
52
 
41
- VALUE obj = rb_tracearg_object(trace_arg);
42
- VALUE klass = RBASIC_CLASS(obj);
53
+ if ( IS_SINGLETON(klass) ) return;
43
54
 
44
- if ( st_lookup(object_counts, (st_data_t) klass, &count) ) {
45
- if ( count > 0 && (count - 1) > 0) {
46
- st_insert(object_counts, (st_data_t) klass, count - 1);
55
+ if ( st_lookup(state->object_counts, (st_data_t) klass, &count) ) {
56
+ if ( count > 0 && (count - 1) > 0 ) {
57
+ st_insert(state->object_counts, (st_data_t) klass, count - 1);
47
58
  }
48
59
  /* Remove the entry if the count is now 0 */
49
60
  else {
50
- st_delete(object_counts, (st_data_t*) &klass, NULL);
61
+ st_delete(state->object_counts, (st_data_t*) &klass, NULL);
51
62
  }
52
63
  }
53
64
  }
@@ -58,9 +69,7 @@ void freeobj_callback(VALUE tracepoint, void* data) {
58
69
  static int each_count(st_data_t key, st_data_t value, st_data_t hash_ptr) {
59
70
  VALUE vkey = (VALUE) key;
60
71
 
61
- if ( rb_obj_is_kind_of(key, rb_cClass) == Qtrue ) {
62
- rb_hash_aset((VALUE) hash_ptr, vkey, INT2NUM(value));
63
- }
72
+ rb_hash_aset((VALUE) hash_ptr, vkey, INT2NUM(value));
64
73
 
65
74
  return ST_CONTINUE;
66
75
  }
@@ -71,19 +80,22 @@ static int each_count(st_data_t key, st_data_t value, st_data_t hash_ptr) {
71
80
  * The returned Hash contains its own copy of the statistics, any further object
72
81
  * allocations/frees will not modify said Hash.
73
82
  *
83
+ * This method ignores singleton classes.
84
+ *
74
85
  * call-seq:
75
86
  * Allocations.to_hash -> Hash
76
87
  */
77
88
  VALUE allocations_to_hash(VALUE self) {
89
+ AllocationState *state = allocation_state_get_struct(state_const);
90
+
78
91
  st_table *local_counts;
79
92
  VALUE hash;
80
93
 
81
- if ( !object_counts ) {
94
+ if ( !state->object_counts ) {
82
95
  return rb_hash_new();
83
96
  }
84
97
 
85
- local_counts = st_copy(object_counts);
86
-
98
+ local_counts = allocation_state_copy_table(state);
87
99
  hash = rb_hash_new();
88
100
 
89
101
  st_foreach(local_counts, each_count, (st_data_t) hash);
@@ -100,11 +112,13 @@ VALUE allocations_to_hash(VALUE self) {
100
112
  * Allocations.start -> nil
101
113
  */
102
114
  VALUE allocations_start(VALUE self) {
115
+ AllocationState *state = allocation_state_get_struct(state_const);
116
+
103
117
  if ( rb_ivar_get(self, id_enabled) == Qtrue ) {
104
118
  return Qnil;
105
119
  }
106
120
 
107
- object_counts = st_init_numtable();
121
+ allocation_state_allocate_counts(state);
108
122
 
109
123
  rb_ivar_set(self, id_enabled, Qtrue);
110
124
 
@@ -121,6 +135,8 @@ VALUE allocations_start(VALUE self) {
121
135
  * Allocations.stop -> nil
122
136
  */
123
137
  VALUE allocations_stop(VALUE self) {
138
+ AllocationState *state = allocation_state_get_struct(state_const);
139
+
124
140
  if ( rb_ivar_get(self, id_enabled) != Qtrue ) {
125
141
  return Qnil;
126
142
  }
@@ -128,11 +144,7 @@ VALUE allocations_stop(VALUE self) {
128
144
  rb_tracepoint_disable(allocation_tracer);
129
145
  rb_tracepoint_disable(free_tracer);
130
146
 
131
- if ( object_counts ) {
132
- st_free_table(object_counts);
133
- }
134
-
135
- object_counts = NULL;
147
+ allocation_state_reset_counts(state);
136
148
 
137
149
  rb_ivar_set(self, id_enabled, Qfalse);
138
150
 
@@ -173,4 +185,8 @@ void Init_liballocations() {
173
185
 
174
186
  rb_define_const(mAllocations, "ALLOCATION_TRACER", allocation_tracer);
175
187
  rb_define_const(mAllocations, "FREE_TRACER", free_tracer);
188
+
189
+ Init_allocations_state();
190
+
191
+ state_const = rb_const_get(mAllocations, rb_intern("STATE"));
176
192
  }
@@ -5,6 +5,8 @@
5
5
  #include <ruby/debug.h>
6
6
  #include <ruby/st.h>
7
7
 
8
+ #include "state.h"
9
+
8
10
  void Init_liballocations();
9
11
 
10
12
  #endif
@@ -0,0 +1,65 @@
1
+ #include "state.h"
2
+
3
+ static int mark_each_entry(st_data_t key, st_data_t value, st_data_t data) {
4
+ rb_gc_mark((VALUE) key);
5
+
6
+ return ST_CONTINUE;
7
+ }
8
+
9
+ // Initializes the table used for storing object counts.
10
+ void allocation_state_allocate_counts(AllocationState *state) {
11
+ state->object_counts = st_init_numtable();
12
+ }
13
+
14
+ // Resets the table used for storing object counts.
15
+ void allocation_state_reset_counts(AllocationState *state) {
16
+ if ( state->object_counts ) {
17
+ st_free_table(state->object_counts);
18
+ }
19
+
20
+ state->object_counts = NULL;
21
+ }
22
+
23
+ // Returns the AllocationState wrapped by `object`
24
+ AllocationState *allocation_state_get_struct(VALUE object) {
25
+ AllocationState *state;
26
+
27
+ Data_Get_Struct(object, AllocationState, state);
28
+
29
+ return state;
30
+ }
31
+
32
+ st_table *allocation_state_copy_table(AllocationState *state) {
33
+ return st_copy(state->object_counts);
34
+ }
35
+
36
+ void allocation_state_mark(AllocationState *state) {
37
+ if ( state->object_counts ) {
38
+ st_foreach(state->object_counts, mark_each_entry, (st_data_t) NULL);
39
+ }
40
+ }
41
+
42
+ void allocation_state_free(AllocationState *state) {
43
+ allocation_state_reset_counts(state);
44
+
45
+ free(state);
46
+ }
47
+
48
+ VALUE allocation_state_allocate(VALUE klass) {
49
+ AllocationState *state = ALLOC(AllocationState);
50
+
51
+ state->object_counts = NULL;
52
+
53
+ return Data_Wrap_Struct(klass, allocation_state_mark, allocation_state_free,
54
+ state);
55
+ }
56
+
57
+ void Init_allocations_state() {
58
+ VALUE mAllocations = rb_const_get(rb_cObject, rb_intern("Allocations"));
59
+ VALUE cState = rb_define_class_under(mAllocations, "State", rb_cObject);
60
+
61
+ rb_define_alloc_func(cState, allocation_state_allocate);
62
+
63
+ rb_define_const(mAllocations, "STATE",
64
+ rb_funcall(cState, rb_intern("new"), 0));
65
+ }
@@ -0,0 +1,17 @@
1
+ #ifndef ALLOCATIONS_STATE_H
2
+ #define ALLOCATIONS_STATE_H
3
+
4
+ #include "liballocations.h"
5
+
6
+ typedef struct {
7
+ st_table *object_counts;
8
+ } AllocationState;
9
+
10
+ extern void allocation_state_reset_counts(AllocationState*);
11
+ extern void allocation_state_allocate_counts(AllocationState*);
12
+ extern AllocationState *allocation_state_get_struct(VALUE object);
13
+ extern st_table *allocation_state_copy_table(AllocationState*);
14
+
15
+ extern void Init_allocations_state();
16
+
17
+ #endif
@@ -1,3 +1,3 @@
1
1
  module Allocations
2
- VERSION = '1.0.4'
2
+ VERSION = '1.0.5'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: allocations
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yorick Peterse
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-15 00:00:00.000000000 Z
11
+ date: 2016-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -79,6 +79,8 @@ files:
79
79
  - ext/liballocations/extconf.rb
80
80
  - ext/liballocations/liballocations.c
81
81
  - ext/liballocations/liballocations.h
82
+ - ext/liballocations/state.c
83
+ - ext/liballocations/state.h
82
84
  - lib/allocations.rb
83
85
  - lib/allocations/version.rb
84
86
  homepage: https://gitlab.com/gitlab-org/allocations