summaryrefslogtreecommitdiff
path: root/test/-ext-
diff options
context:
space:
mode:
authorDaisuke Aritomo <osyoyu@osyoyu.com>2023-09-29 15:35:36 +0900
committerKoichi Sasada <ko1@atdot.net>2023-10-31 11:16:18 +0900
commit4adf418be963b3554962b2f27057be81486c57d9 (patch)
treed43c3006925aaacdf522b58b752b860f6b94875a /test/-ext-
parent02ecc3c8550af1aab7916975e7019b2a3ffe8591 (diff)
[Feature #10602] Add new API rb_profile_thread_frames()
Add a new API rb_profile_thread_frames(), which is essentialy a per-thread version of rb_profile_frames(). While the original rb_profile_frames() always returns results about the current active thread obtained by GET_EC(), this new API takes a Thread to be profiled as an argument. This should come in handy when profiling I/O-bound programs such as webapps, since this new API allows us to learn about Threads performing I/O (which do not have the GVL). Profiling worker threads (such as Sidekiq workers) may be another application. Implements [Feature #10602] Co-authored-by: Mike Perham <mike@perham.net>
Diffstat (limited to 'test/-ext-')
-rw-r--r--test/-ext-/debug/test_profile_frames.rb47
1 files changed, 47 insertions, 0 deletions
diff --git a/test/-ext-/debug/test_profile_frames.rb b/test/-ext-/debug/test_profile_frames.rb
index 08aedf63c8..e66413c228 100644
--- a/test/-ext-/debug/test_profile_frames.rb
+++ b/test/-ext-/debug/test_profile_frames.rb
@@ -39,6 +39,20 @@ class SampleClassForTestProfileFrames
end
end
+class SampleClassForTestProfileThreadFrames
+ def initialize(mutex)
+ @mutex = mutex
+ end
+
+ def foo(block)
+ bar(block)
+ end
+
+ def bar(block)
+ block.call
+ end
+end
+
class TestProfileFrames < Test::Unit::TestCase
def test_profile_frames
obj, frames = Fiber.new{
@@ -139,6 +153,39 @@ class TestProfileFrames < Test::Unit::TestCase
}
end
+ def test_profile_thread_frames
+ mutex = Mutex.new
+ th = Thread.new do
+ mutex.lock
+ Thread.stop
+ SampleClassForTestProfileThreadFrames.new(mutex).foo(lambda { mutex.unlock; loop { sleep(1) } } )
+ end
+
+ # ensure execution has reached SampleClassForTestProfileThreadFrames#bar before running profile_thread_frames
+ loop { break if th.status == "sleep"; sleep 0.1 }
+ th.run
+ mutex.lock # wait until SampleClassForTestProfileThreadFrames#bar has been called
+
+ frames = Bug::Debug.profile_thread_frames(th, 0, 10)
+
+ full_labels = [
+ "Kernel#sleep",
+ "TestProfileFrames#test_profile_thread_frames",
+ "Kernel#loop",
+ "TestProfileFrames#test_profile_thread_frames",
+ "SampleClassForTestProfileThreadFrames#bar",
+ "SampleClassForTestProfileThreadFrames#foo",
+ "TestProfileFrames#test_profile_thread_frames",
+ ]
+
+ frames.each.with_index do |frame, i|
+ assert_equal(full_labels[i], frame)
+ end
+
+ th.kill
+ end
+
+
def test_matches_backtrace_locations_main_thread
assert_equal(Thread.current, Thread.main)