summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYusuke Endoh <mame@ruby-lang.org>2021-05-14 13:40:32 +0900
committerYusuke Endoh <mame@ruby-lang.org>2021-05-14 13:40:32 +0900
commitcf1e1879f12ad547f95fe94ab62b4d960e804eb8 (patch)
treee96d145838260a4782707955ec23f5d0c6798f01
parent7cf90f99f5674fdadc0ff9d8341b315b2490ea26 (diff)
ext/objspace/lib/objspace/trace.rb: Added
This file, when require'ed, starts tracing the object allocations, and redefines `Kernel#p` to show the allocation site. This commit is experimental; the library name and APIs may change. [Feature #17762]
-rw-r--r--ext/objspace/lib/objspace/trace.rb44
-rw-r--r--test/objspace/test_objspace.rb16
2 files changed, 60 insertions, 0 deletions
diff --git a/ext/objspace/lib/objspace/trace.rb b/ext/objspace/lib/objspace/trace.rb
new file mode 100644
index 0000000000..df803bbae6
--- /dev/null
+++ b/ext/objspace/lib/objspace/trace.rb
@@ -0,0 +1,44 @@
+# This is a simple tool to enable the object allocation tracer.
+# When you have an object of unknown provenance, you can use this
+# to investigate where the object in question is created.
+#
+# = Important notice
+#
+# This is only for debugging purpose. Do not use this in production.
+# Require'ing this file immediately starts tracing the object allocation,
+# which brings a large performance overhead.
+#
+# = Usage
+#
+# 1. Add `require "objspace/trace"` into your code (or add `-robjspace/trace` into the command line)
+# 2. `p obj` will show the allocation site of `obj`
+#
+# Note: This redefines `Kernel#p` method, but not `Object#inspect`.
+#
+# = Examples
+#
+# 1: require "objspace/trace"
+# 2:
+# 3: obj = "str"
+# 4:
+# 5: p obj #=> "str" @ test.rb:3
+
+require 'objspace.so'
+
+module Kernel
+ define_method(:p) do |*objs|
+ objs.each do |obj|
+ file = ObjectSpace.allocation_sourcefile(obj)
+ line = ObjectSpace.allocation_sourceline(obj)
+ if file
+ puts "#{ obj.inspect } @ #{ file }:#{ line }"
+ else
+ puts obj.inspect
+ end
+ end
+ end
+end
+
+ObjectSpace.trace_object_allocations_start
+
+warn "objspace/trace is enabled"
diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb
index 7032798940..7797d199fa 100644
--- a/test/objspace/test_objspace.rb
+++ b/test/objspace/test_objspace.rb
@@ -616,4 +616,20 @@ class TestObjSpace < Test::Unit::TestCase
assert_not_include ObjectSpace.dump(Class.new), '"name"'
assert_not_include ObjectSpace.dump(Module.new), '"name"'
end
+
+ def test_objspace_trace
+ assert_in_out_err(%w[-robjspace/trace], "#{<<-"begin;"}\n#{<<-'end;'}") do |out, err|
+ begin;
+ a = "foo"
+ b = "b" + "a" + "r"
+ c = 42
+ p a, b, c
+ end;
+ assert_equal 3, out.size
+ assert_equal '"foo" @ -:2', out[0]
+ assert_equal '"bar" @ -:3', out[1]
+ assert_equal '42', out[2]
+ assert_equal ["objspace/trace is enabled"], err
+ end
+ end
end