alloc_track 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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