objspace_helpers 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: 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: