objspace_helpers 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: d0175d9d52d2d5fdc414e9b5e9cda0475dcf33bd
4
- data.tar.gz: 5c92f3b27147ecef0e63a55332a3c72262d78f68
3
+ metadata.gz: cbb176043e7fcf26f81faec74c26725353c914aa
4
+ data.tar.gz: 3dd9ba529a9b4fbc949cecf0f085c542858d46c6
5
5
  SHA512:
6
- metadata.gz: 4a31190183b4d4d8b1d348720dd4a974c3fed2410184dcaeac3ffdef6263785cde179398581cb60b2b518e723470a82cf5926193270c5cdbd25363bcbd893c60
7
- data.tar.gz: ec1a6ff89ac9d196d12eb791ab8abf0f70b993e7d5b552b6f51691a25b663e63999173d0930daa2b6a2f12ce622f542186670fb2b9cc6fe3ed80093945acd9bf
6
+ metadata.gz: 14b5bb3c4aed3a80f68c7873cf681cb6e0df30452ccdc2bf4908649aed509338ef06b7be47aef212798e4e4874e478114ea2b7af01f461d601409313c5f38312
7
+ data.tar.gz: 60219c051f2596767b4aa28b9a5178a98255a6ec91e9e7862e87014926658b724e07332853a0ab0c3038e5a78c29c7237ffdfa86000501b0a2248607e44dc15e
@@ -0,0 +1,46 @@
1
+ /* Note (LukasFittl): Copy of ObjectSpace._id2ref from Ruby 2.1 source,
2
+ * directly callable without the VM overhead, and more foregiving for internal objects.
3
+ */
4
+
5
+ #include <id2ref.h>
6
+
7
+ #if SIZEOF_LONG == SIZEOF_VOIDP
8
+ # define nonspecial_obj_id(obj) (VALUE)((SIGNED_VALUE)(obj)|FIXNUM_FLAG)
9
+ # define obj_id_to_ref(objid) ((objid) ^ FIXNUM_FLAG) /* unset FIXNUM_FLAG */
10
+ #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
11
+ # define nonspecial_obj_id(obj) LL2NUM((SIGNED_VALUE)(obj) / 2)
12
+ # define obj_id_to_ref(objid) (FIXNUM_P(objid) ? \
13
+ ((objid) ^ FIXNUM_FLAG) : (NUM2PTR(objid) << 1))
14
+ #else
15
+ # error not supported
16
+ #endif
17
+
18
+ VALUE
19
+ oh_id2ref(VALUE self, VALUE objid)
20
+ {
21
+ #if SIZEOF_LONG == SIZEOF_VOIDP
22
+ #define NUM2PTR(x) NUM2ULONG(x)
23
+ #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
24
+ #define NUM2PTR(x) NUM2ULL(x)
25
+ #endif
26
+ VALUE ptr;
27
+ void *p0;
28
+
29
+ ptr = NUM2PTR(objid);
30
+ p0 = (void *)ptr;
31
+
32
+ if (ptr == Qtrue) return Qtrue;
33
+ if (ptr == Qfalse) return Qfalse;
34
+ if (ptr == Qnil) return Qnil;
35
+ if (FIXNUM_P(ptr)) return (VALUE)ptr;
36
+ if (FLONUM_P(ptr)) return (VALUE)ptr;
37
+ ptr = obj_id_to_ref(objid);
38
+
39
+ if ((ptr % rb_intern("RVALUE_SIZE")) == (4 << 2)) {
40
+ ID symid = ptr / rb_intern("RVALUE_SIZE");
41
+ if (rb_id2name(symid) == 0) return Qundef;
42
+ return ID2SYM(symid);
43
+ }
44
+
45
+ return (VALUE)ptr;
46
+ }
@@ -0,0 +1,9 @@
1
+ #ifndef RUBY_ID2REF
2
+ #define RUBY_ID2REF
3
+
4
+ #include <ruby.h>
5
+ #include <ruby_private/gc.h>
6
+
7
+ VALUE oh_id2ref(VALUE self, VALUE objid);
8
+
9
+ #endif
@@ -0,0 +1,55 @@
1
+ class ObjspaceHelpers
2
+ class << self
3
+ def find_leaks(trace: false, &block)
4
+ ObjectSpace::trace_object_allocations_start if trace
5
+
6
+ objs_before = _dump_addresses
7
+
8
+ block.call
9
+
10
+ # Run GC twice to try to get rid of as much false positives as possible
11
+ ObjectSpace.garbage_collect
12
+ ObjectSpace.garbage_collect
13
+
14
+ objs_after = _dump_addresses
15
+
16
+ ObjectSpace::trace_object_allocations_stop if trace
17
+
18
+ leaked_addresses = objs_after - objs_before - [objs_after.object_id]
19
+
20
+ GC.disable
21
+
22
+ # Note (LukasFittl): 2x speedup if we move this to native code
23
+ referenced_by = {}
24
+ _addresses_to_references(objs_after).each do |addr, references|
25
+ (references & leaked_addresses).each do |ref|
26
+ referenced_by[ref] ||= []
27
+ referenced_by[ref] << addr
28
+ end
29
+ end
30
+
31
+ GC.enable
32
+
33
+ TrackedObject.wrap(leaked_addresses, referenced_by)
34
+ end
35
+
36
+ def find_leak_sources(trace: false, &block)
37
+ leaks = find_leaks(trace: trace, &block)
38
+ leaks_by_source = {}
39
+ top_level_leaks = []
40
+
41
+ leaks.each do |leak|
42
+ if leak.referenced_by.empty?
43
+ top_level_leaks << leak
44
+ else
45
+ leak.referenced_by.each do |source|
46
+ leaks_by_source[source] ||= []
47
+ leaks_by_source[source] << leak
48
+ end
49
+ end
50
+ end
51
+
52
+ [top_level_leaks, leaks_by_source]
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,31 @@
1
+ class ObjspaceHelpers::TrackedObject
2
+ def self.wrap(addresses, referenced_by = [])
3
+ Array.new(addresses || []).map do |address|
4
+ new(address, wrap(referenced_by[address]))
5
+ end
6
+ end
7
+
8
+ def self.for_object(obj)
9
+ new ObjspaceHelpers._address_of_obj(obj)
10
+ end
11
+
12
+ attr_reader :address
13
+ attr_reader :referenced_by
14
+
15
+ def initialize(address, referenced_by = [])
16
+ @address = address
17
+ @referenced_by = referenced_by
18
+ end
19
+
20
+ def info
21
+ ObjspaceHelpers._addresses_to_info([@address]).values.first
22
+ end
23
+
24
+ def klass
25
+ self.class.new(info['class'])
26
+ end
27
+
28
+ def dereference
29
+ ObjspaceHelpers._id2ref(@address)
30
+ end
31
+ end
@@ -1,3 +1,3 @@
1
1
  class ObjspaceHelpers
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: objspace_helpers
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
  - Lukas Fittl
@@ -62,6 +62,8 @@ files:
62
62
  - LICENSE
63
63
  - Rakefile
64
64
  - ext/objspace_helpers/extconf.rb
65
+ - ext/objspace_helpers/id2ref.c
66
+ - ext/objspace_helpers/id2ref.h
65
67
  - ext/objspace_helpers/objspace_helpers.c
66
68
  - ext/objspace_helpers/objspace_helpers.h
67
69
  - ext/objspace_helpers/objspace_info.c
@@ -71,6 +73,8 @@ files:
71
73
  - ext/objspace_helpers/ruby_private/objspace.h
72
74
  - lib/objspace_helpers.rb
73
75
  - lib/objspace_helpers/helpers.rb
76
+ - lib/objspace_helpers/leaks.rb
77
+ - lib/objspace_helpers/tracked_object.rb
74
78
  - lib/objspace_helpers/version.rb
75
79
  homepage: http://github.com/lfittl/objspace_helpers
76
80
  licenses: