alloc_track 0.0.2 → 0.0.3

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: c2bcef216fe18bd1578ecc1b47f26e10cf6669ad
4
- data.tar.gz: 2f003bcc8dc4f0f30a7123518192fb7c9a3c22da
3
+ metadata.gz: 996bfa135ead01bfda01be1bfc01a20eae7e99b8
4
+ data.tar.gz: 634b89b83837795cac2491ba924ef96a5404856f
5
5
  SHA512:
6
- metadata.gz: 50d0ecf47e7a19ac2f9b59e484ab84e8379243d25c7a31487be87924d6b4f486bdecb50613874fcdc07b98a90b1c60946d264257df4597cab590233ebbd6b142
7
- data.tar.gz: 86ee7fc454d489abb83df54d01d6fb226da1f0d66f56e5dacc764bf02fbc173494b3ef0bfe1abf2af7f159a978899ca05c4e3c8030c15d62d3bbb743c009a7e7
6
+ metadata.gz: 2c37c97d902cc8c35130169c50807a731d4472a111b53f1204ecf63a9f96b7dc5dce4c54e7dc579636964fe5e7868d9c007b58dd71d419f6df02464ca0e8504d
7
+ data.tar.gz: 98fee067ef40dfbcf8dc71224b043a13b6974ebd3b4fbe0bcf0cdde03e74629f2d2aaecaaf06e3c0c9d75cb8cc69b5a67f7dab756516e8b2b50f072351ebdeb3
data/.gitignore CHANGED
@@ -2,3 +2,4 @@
2
2
  /lib/alloc_track/*.so
3
3
  /lib/alloc_track/*.bundle
4
4
  /tmp/*
5
+ alloc_track-*.gem
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- alloc_track (0.0.1)
4
+ alloc_track (0.0.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'alloc_track'
3
- s.version = '0.0.2'
3
+ s.version = '0.0.3'
4
4
  s.summary = 'allocation tracker for ruby 2.1+'
5
5
  s.description = 'tracks memory allocations with rgengc in ruby 2.1'
6
6
 
@@ -2,15 +2,18 @@
2
2
  #include "ruby/intern.h"
3
3
  #include "ruby/debug.h"
4
4
 
5
- #define ALLOCTRACK_OBJ_BIT FL_USER18
5
+ #define ALLOCTRACK_OBJ_BIT FL_USER19
6
+
7
+ #define MAX(_x, _y) ( (_x) > (_y) ? (_x) : (_y) )
6
8
 
7
9
  typedef struct stat_collector {
8
10
  struct stat_collector *next; /* not currently used */
9
11
  VALUE thread;
10
- int current_alloc;
11
- int current_free;
12
- int current_limit;
13
- int limit_signal;
12
+ int64_t current_alloc;
13
+ int64_t current_free;
14
+ int64_t current_limit;
15
+ int limit_signal;
16
+ int64_t max_delta;
14
17
  } stat_collector_t;
15
18
 
16
19
  static VALUE mAllocTrack;
@@ -124,14 +127,14 @@ static VALUE
124
127
  alloc()
125
128
  {
126
129
  validate_started();
127
- return INT2FIX(get_collector(rb_thread_current())->current_alloc);
130
+ return LL2NUM(get_collector(rb_thread_current())->current_alloc);
128
131
  }
129
132
 
130
133
  static VALUE
131
134
  _free()
132
135
  {
133
136
  validate_started();
134
- return INT2FIX(get_collector(rb_thread_current())->current_free);
137
+ return LL2NUM(get_collector(rb_thread_current())->current_free);
135
138
  }
136
139
 
137
140
  static VALUE
@@ -140,7 +143,16 @@ delta()
140
143
  stat_collector_t *c;
141
144
  validate_started();
142
145
  c = get_collector(rb_thread_current());
143
- return INT2FIX(c->current_alloc - c->current_free);
146
+ return LL2NUM(c->current_alloc - c->current_free);
147
+ }
148
+
149
+ static VALUE
150
+ max_delta()
151
+ {
152
+ stat_collector_t *c;
153
+ validate_started();
154
+ c = get_collector(rb_thread_current());
155
+ return LL2NUM(c->max_delta);
144
156
  }
145
157
 
146
158
  static VALUE
@@ -173,12 +185,6 @@ limit(VALUE self, VALUE num_allocs)
173
185
  return rb_ensure(do_limit, num_allocs, ensure_stopped, Qnil);
174
186
  }
175
187
 
176
- static int
177
- is_collector_enabled(stat_collector_t *c)
178
- {
179
- return c->limit_signal == 0 ? 1 : 0;
180
- }
181
-
182
188
  static int
183
189
  is_collector_limit_exceeded(stat_collector_t *c)
184
190
  {
@@ -194,9 +200,10 @@ tracepoint_hook(VALUE tpval, void *data)
194
200
  VALUE obj = rb_tracearg_object(tparg);
195
201
  switch(flag) {
196
202
  case RUBY_INTERNAL_EVENT_NEWOBJ:
197
- if ((c = get_collector(rb_thread_current())) != NULL && is_collector_enabled(c)) {
203
+ if ((c = get_collector(rb_thread_current())) != NULL) {
198
204
  RBASIC(obj)->flags |= ALLOCTRACK_OBJ_BIT;
199
205
  c->current_alloc++;
206
+ c->max_delta = MAX( c->current_alloc - c->current_free, c->max_delta);
200
207
 
201
208
  if (c->current_limit && (c->current_alloc - c->current_free) > c->current_limit) {
202
209
  c->limit_signal = 1;
@@ -212,8 +219,7 @@ tracepoint_hook(VALUE tpval, void *data)
212
219
  }
213
220
  break;
214
221
  case RUBY_INTERNAL_EVENT_FREEOBJ:
215
- if ((c = get_collector(rb_thread_current())) != NULL && is_collector_enabled(c) &&
216
- (RBASIC(obj)->flags & ALLOCTRACK_OBJ_BIT)) {
222
+ if ((c = get_collector(rb_thread_current())) != NULL && (RBASIC(obj)->flags & ALLOCTRACK_OBJ_BIT)) {
217
223
  c->current_free++;
218
224
  }
219
225
  break;
@@ -235,14 +241,22 @@ any_collectors_with_exceeded_limits()
235
241
  static void
236
242
  exception_tracepoint_hook(VALUE tpval, void *data)
237
243
  {
244
+ int should_raise = 0;
238
245
  VALUE th = rb_thread_current();
239
246
  stat_collector_t *c;
240
247
  if ((c = get_collector(th)) != NULL && is_collector_limit_exceeded(c)) {
241
- remove_collector(th);
248
+ rb_gc(); /* try to gc before raising */
249
+ if ((c->current_alloc - c->current_free) > c->current_limit) {
250
+ remove_collector(th);
251
+ should_raise = 1;
252
+ } else {
253
+ c->limit_signal = 0;
254
+ }
242
255
  if (!any_collectors_with_exceeded_limits()) {
243
256
  rb_tracepoint_disable(tpval_exception);
244
257
  }
245
- rb_raise(eAllocTrackLimitExceeded, "allocation limit exceeded");
258
+
259
+ if (should_raise) rb_raise(eAllocTrackLimitExceeded, "allocation limit exceeded");
246
260
  }
247
261
  }
248
262
 
@@ -258,6 +272,7 @@ Init_alloc_track()
258
272
  rb_define_singleton_method(mAllocTrack, "free", _free, 0);
259
273
  rb_define_singleton_method(mAllocTrack, "delta", delta, 0);
260
274
  rb_define_singleton_method(mAllocTrack, "limit", limit, 1);
275
+ rb_define_singleton_method(mAllocTrack, "max_delta", max_delta, 0);
261
276
 
262
277
  eAllocTrackError = rb_define_class_under(mAllocTrack, "Error", rb_eStandardError);
263
278
  eAllocTrackLimitExceeded = rb_define_class_under(mAllocTrack, "LimitExceeded", rb_eStandardError);
@@ -19,6 +19,17 @@ class TestAllocTrack < Test::Unit::TestCase
19
19
  AllocTrack.stop
20
20
  end
21
21
 
22
+ def test_max_delta
23
+ AllocTrack.start
24
+ max_delta = 0
25
+ 100.times do
26
+ Object.new
27
+ max_delta = [max_delta, AllocTrack.delta].max
28
+ end
29
+ assert (AllocTrack.max_delta - max_delta ).abs < 10 #close enough
30
+ AllocTrack.stop
31
+ end
32
+
22
33
  def test_thread_not_included
23
34
  AllocTrack.start
24
35
  t = Thread.new do
@@ -49,11 +60,22 @@ class TestAllocTrack < Test::Unit::TestCase
49
60
  end
50
61
 
51
62
  def test_limit_raises
63
+ vals = []
52
64
  assert_raise AllocTrack::LimitExceeded do
53
65
  AllocTrack.limit 10 do
66
+ 200.times { vals.push(Object.new) }
67
+ end
68
+ end
69
+ end
70
+
71
+ def test_limit_invokes_gc
72
+ stat = GC.stat
73
+ assert_nothing_raised do
74
+ AllocTrack.limit 50 do
54
75
  200.times { Object.new }
55
76
  end
56
77
  end
78
+ assert_operator GC.stat[:count], :>, stat[:count]
57
79
  end
58
80
 
59
81
  def test_within_limit
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alloc_track
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Francis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-05 00:00:00.000000000 Z
11
+ date: 2015-03-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler