Skip to content

Instantly share code, notes, and snippets.

@x-yuri
Last active September 14, 2024 12:26
Show Gist options
  • Save x-yuri/8571cd81faeef0bf576b92e1797d1076 to your computer and use it in GitHub Desktop.
Save x-yuri/8571cd81faeef0bf576b92e1797d1076 to your computer and use it in GitHub Desktop.
ruby: using RUBY_DEBUG_LOG

ruby: using RUBY_DEBUG_LOG

Build with cflags=-DUSE_RUBY_DEBUG_LOG, run with RUBY_DEBUG_LOG=stderr RUBY_DEBUG_LOG_FILTER=... ruby ....

/* RUBY_DEBUG_LOG: Logging debug information mechanism
 *
 * This feature provides a mechanism to store logging information
 * to a file, stderr or memory space with simple macros.
 *
 * The following information will be stored.
 *   * (1) __FILE__, __LINE__ in C
 *   * (2) __FILE__, __LINE__ in Ruby
 *   * (3) __func__ in C (message title)
 *   * (4) given string with sprintf format
 *   * (5) Thread number (if multiple threads are running)
 *
 * This feature is enabled only USE_RUBY_DEBUG_LOG is enabled.
 * Release version should not enable it.
 *
 * Running with the `RUBY_DEBUG_LOG` environment variable enables
 * this feature.
 *
 *   # logging into a file
 *   RUBY_DEBUG_LOG=/path/to/file STDERR
 *
 *   # logging into STDERR
 *   RUBY_DEBUG_LOG=stderr
 *
 *   # logging into memory space (check with a debugger)
 *   # It will help if the timing is important.
 *   RUBY_DEBUG_LOG=mem
 *
 * RUBY_DEBUG_LOG_FILTER environment variable can specify the filter string.
 * If "(3) __func__ in C (message title)" contains the specified string, the
 * information will be stored (example: RUBY_DEBUG_LOG_FILTER=str will enable
 * only on str related information).
 *
 * In a MRI source code, you can use the following macros:
 *   * RUBY_DEBUG_LOG(fmt, ...): Above (1) to (4) will be logged.
 *   * RUBY_DEBUG_LOG2(file, line, fmt, ...):
 *     Same as RUBY_DEBUG_LOG(), but (1) will be replaced with given file, line.
 */

https://github.com/ruby/ruby/blob/v3_3_5/vm_debug.h#L38-L75

// RUBY_DEBUG_LOG_FILTER=-foo,-bar,baz,boo
// returns true if
//   (func_name or file_name) doesn't contain foo
// and
//   (func_name or file_name) doesn't contain bar
// and
//   (func_name or file_name) contains baz or boo
//
// RUBY_DEBUG_LOG_FILTER=foo,bar,-baz,-boo
// returns true if
//   (func_name or file_name) contains foo or bar
// or
//   (func_name or file_name) doesn't contain baz and
//   (func_name or file_name) doesn't contain boo and
//
// You can specify "file:" (ex file:foo) or "func:" (ex  func:foo)
// prefixes to specify the filter for.

https://github.com/ruby/ruby/blob/v3_3_5/debug.c#L485-L503

a.sh:

docker run --rm -t -v /tmp/a.rb:/a.rb -v /tmp/a.patch:/a.patch alpine:3.20.3 sh -euxc '
    apk add git build-base autoconf ruby yaml-dev zlib-dev openssl-dev libffi-dev
    git clone https://github.com/ruby/ruby
    cd ruby
    git checkout v3_3_5
    patch -p1 < /a.patch
    ./autogen.sh
    ./configure cflags=-DUSE_RUBY_DEBUG_LOG --disable-install-doc
    make -j8 install
    RUBY_DEBUG_LOG=stderr RUBY_DEBUG_LOG_FILTER=rb_thread_schedule_limits,rb_ractor_thread_switch ruby --disable=gems /a.rb
'

a.patch:

diff --git a/thread.c b/thread.c
index 104205beb2..375d6a66ac 100644
--- a/thread.c
+++ b/thread.c
@@ -1447,10 +1447,10 @@ rb_thread_schedule_limits(uint32_t limits_us)
 {
     if (!rb_thread_alone()) {
         rb_thread_t *th = GET_THREAD();
-        RUBY_DEBUG_LOG("us:%u", (unsigned int)limits_us);
+        // RUBY_DEBUG_LOG("us:%u", (unsigned int)limits_us);
 
         if (th->running_time_us >= limits_us) {
-            RUBY_DEBUG_LOG("switch %s", "start");
+            RUBY_DEBUG_LOG("switch %s (running_time_us: %u, limits_us: %u)", "start", th->running_time_us, limits_us);
 
             RB_VM_SAVE_MACHINE_CONTEXT(th);
             thread_sched_yield(TH_SCHED(th), th);

a.rb:

puts "-- start"
3.times.map {
  Thread.new {
    (1..10_000_000).reduce(:+)
  }
}.each(&:join)
puts "-- end"
$ sh a.sh
...
-- start
  16: rb_ractor_thread_switch   th:1->1 (same)  ractor_core.h:288       a.rb:1  nt:1    th:1
  17: rb_ractor_thread_switch   th:3->2 ractor_core.h:288               nt:2    th:2 (rth:3,sth:2)
  18: rb_thread_schedule_limits switch start (running_time_us: 100000, limits_us: 100000)       thread.c:1455   a.rb:4  nt:2    th:2 (rth:4,sth:2)
  19: rb_ractor_thread_switch   th:4->3 ractor_core.h:288               nt:3    th:3 (rth:4,sth:3)
  20: rb_thread_schedule_limits switch start (running_time_us: 100000, limits_us: 100000)       thread.c:1455   a.rb:4  nt:3    th:3
  21: rb_ractor_thread_switch   th:3->4 ractor_core.h:288               nt:4    th:4 (rth:3,sth:4)
  22: rb_thread_schedule_limits switch start (running_time_us: 100000, limits_us: 100000)       thread.c:1455   a.rb:4  nt:4    th:4
  23: rb_ractor_thread_switch   th:4->2 ractor_core.h:288       a.rb:4  nt:2    th:2 (rth:4,sth:2)
  24: rb_ractor_thread_switch   th:2->2 (same)  ractor_core.h:288       a.rb:4  nt:2    th:2
  25: rb_thread_schedule_limits switch done     thread.c:1461   a.rb:4  nt:2    th:2
  26: rb_thread_schedule_limits switch start (running_time_us: 100000, limits_us: 100000)       thread.c:1455   a.rb:4  nt:2    th:2
  27: rb_ractor_thread_switch   th:2->3 ractor_core.h:288       a.rb:4  nt:3    th:3 (rth:2,sth:3)
  28: rb_ractor_thread_switch   th:3->3 (same)  ractor_core.h:288       a.rb:4  nt:3    th:3
  29: rb_thread_schedule_limits switch done     thread.c:1461   a.rb:4  nt:3    th:3
  30: rb_thread_schedule_limits switch start (running_time_us: 100000, limits_us: 100000)       thread.c:1455   a.rb:4  nt:3    th:3
  31: rb_ractor_thread_switch   th:3->4 ractor_core.h:288       a.rb:4  nt:4    th:4 (rth:3,sth:4)
  32: rb_ractor_thread_switch   th:4->4 (same)  ractor_core.h:288       a.rb:4  nt:4    th:4
  33: rb_thread_schedule_limits switch done     thread.c:1461   a.rb:4  nt:4    th:4
  34: rb_thread_schedule_limits switch start (running_time_us: 100000, limits_us: 100000)       thread.c:1455   a.rb:4  nt:4    th:4
  35: rb_ractor_thread_switch   th:4->2 ractor_core.h:288       a.rb:4  nt:2    th:2 (rth:4,sth:2)
  36: rb_ractor_thread_switch   th:2->2 (same)  ractor_core.h:288       a.rb:4  nt:2    th:2
  37: rb_thread_schedule_limits switch done     thread.c:1461   a.rb:4  nt:2    th:2
  38: rb_thread_schedule_limits switch start (running_time_us: 100000, limits_us: 100000)       thread.c:1455   a.rb:4  nt:2    th:2
  39: rb_ractor_thread_switch   th:2->3 ractor_core.h:288       a.rb:4  nt:3    th:3 (rth:2,sth:3)
  40: rb_ractor_thread_switch   th:3->3 (same)  ractor_core.h:288       a.rb:4  nt:3    th:3
  41: rb_thread_schedule_limits switch done     thread.c:1461   a.rb:4  nt:3    th:3
  42: rb_thread_schedule_limits switch start (running_time_us: 100000, limits_us: 100000)       thread.c:1455   a.rb:4  nt:3    th:3
  43: rb_ractor_thread_switch   th:3->4 ractor_core.h:288       a.rb:4  nt:4    th:4 (rth:3,sth:4)
  44: rb_ractor_thread_switch   th:4->4 (same)  ractor_core.h:288       a.rb:4  nt:4    th:4
  45: rb_thread_schedule_limits switch done     thread.c:1461   a.rb:4  nt:4    th:4
  46: rb_thread_schedule_limits switch start (running_time_us: 100000, limits_us: 100000)       thread.c:1455   a.rb:4  nt:4    th:4
  47: rb_ractor_thread_switch   th:4->2 ractor_core.h:288       a.rb:4  nt:2    th:2 (rth:4,sth:2)
  48: rb_ractor_thread_switch   th:2->2 (same)  ractor_core.h:288       a.rb:4  nt:2    th:2
  49: rb_thread_schedule_limits switch done     thread.c:1461   a.rb:4  nt:2    th:2
  50: rb_thread_schedule_limits switch start (running_time_us: 100000, limits_us: 100000)       thread.c:1455   a.rb:4  nt:2    th:2
  51: rb_ractor_thread_switch   th:2->3 ractor_core.h:288       a.rb:4  nt:3    th:3 (rth:2,sth:3)
  52: rb_ractor_thread_switch   th:3->3 (same)  ractor_core.h:288       a.rb:4  nt:3    th:3
  53: rb_thread_schedule_limits switch done     thread.c:1461   a.rb:4  nt:3    th:3
  54: rb_thread_schedule_limits switch start (running_time_us: 100000, limits_us: 100000)       thread.c:1455   a.rb:4  nt:3    th:3
  55: rb_ractor_thread_switch   th:3->4 ractor_core.h:288       a.rb:4  nt:4    th:4 (rth:3,sth:4)
  56: rb_ractor_thread_switch   th:4->4 (same)  ractor_core.h:288       a.rb:4  nt:4    th:4
  57: rb_thread_schedule_limits switch done     thread.c:1461   a.rb:4  nt:4    th:4
  58: rb_thread_schedule_limits switch start (running_time_us: 100000, limits_us: 100000)       thread.c:1455   a.rb:4  nt:4    th:4
  59: rb_ractor_thread_switch   th:4->2 ractor_core.h:288       a.rb:4  nt:2    th:2 (rth:4,sth:2)
  60: rb_ractor_thread_switch   th:2->2 (same)  ractor_core.h:288       a.rb:4  nt:2    th:2
  61: rb_thread_schedule_limits switch done     thread.c:1461   a.rb:4  nt:2    th:2
  62: rb_thread_schedule_limits switch start (running_time_us: 100000, limits_us: 100000)       thread.c:1455   a.rb:4  nt:2    th:2
  63: rb_ractor_thread_switch   th:2->3 ractor_core.h:288       a.rb:4  nt:3    th:3 (rth:2,sth:3)
  64: rb_ractor_thread_switch   th:3->3 (same)  ractor_core.h:288       a.rb:4  nt:3    th:3
  65: rb_thread_schedule_limits switch done     thread.c:1461   a.rb:4  nt:3    th:3
  66: rb_thread_schedule_limits switch start (running_time_us: 100000, limits_us: 100000)       thread.c:1455   a.rb:4  nt:3    th:3
  67: rb_ractor_thread_switch   th:3->4 ractor_core.h:288       a.rb:4  nt:4    th:4 (rth:3,sth:4)
  68: rb_ractor_thread_switch   th:4->4 (same)  ractor_core.h:288       a.rb:4  nt:4    th:4
  69: rb_thread_schedule_limits switch done     thread.c:1461   a.rb:4  nt:4    th:4
  70: rb_thread_schedule_limits switch start (running_time_us: 100000, limits_us: 100000)       thread.c:1455   a.rb:4  nt:4    th:4
  71: rb_ractor_thread_switch   th:4->2 ractor_core.h:288       a.rb:4  nt:2    th:2 (rth:4,sth:2)
  72: rb_ractor_thread_switch   th:2->2 (same)  ractor_core.h:288       a.rb:4  nt:2    th:2
  73: rb_thread_schedule_limits switch done     thread.c:1461   a.rb:4  nt:2    th:2
  74: rb_ractor_thread_switch   th:2->3 ractor_core.h:288       a.rb:4  nt:3    th:3 (rth:2,sth:3)
  75: rb_ractor_thread_switch   th:3->3 (same)  ractor_core.h:288       a.rb:4  nt:3    th:3
  76: rb_thread_schedule_limits switch done     thread.c:1461   a.rb:4  nt:3    th:3
  77: rb_ractor_thread_switch   th:3->4 ractor_core.h:288       a.rb:4  nt:4    th:4 (rth:3,sth:4)
  78: rb_ractor_thread_switch   th:4->4 (same)  ractor_core.h:288       a.rb:4  nt:4    th:4
  79: rb_thread_schedule_limits switch done     thread.c:1461   a.rb:4  nt:4    th:4
  80: rb_ractor_thread_switch   th:4->1 ractor_core.h:288       a.rb:6  nt:1    th:1 (rth:4,sth:1)
-- end
  81: rb_ractor_thread_switch   th:1->1 (same)  ractor_core.h:288       a.rb:7  nt:1    th:1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment