ruby-changes:63782
From: Takashi <ko1@a...>
Date: Sat, 28 Nov 2020 16:07:12 +0900 (JST)
Subject: [ruby-changes:63782] 122cd35939 (master): Throttle unload_units
https://git.ruby-lang.org/ruby.git/commit/?id=122cd35939 From 122cd35939ddf8ef7bfa17ad75570c01d0cf06ab Mon Sep 17 00:00:00 2001 From: Takashi Kokubun <takashikkbn@g...> Date: Fri, 27 Nov 2020 22:46:01 -0800 Subject: Throttle unload_units Because d80226e7bd often reduces the number of unloaded units, it increases the number of unload_units calls, which are heavy. To mitigate that, this throttles unload_units per `max_cache_size / 10`. Also hoping to fix https://ci.appveyor.com/project/ruby/ruby/builds/36552382/job/kjmjgw9cjyf2ksd7 diff --git a/mjit.c b/mjit.c index 94857df..c65355f 100644 --- a/mjit.c +++ b/mjit.c @@ -261,7 +261,7 @@ mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_inf https://github.com/ruby/ruby/blob/trunk/mjit.c#L261 CRITICAL_SECTION_START(3, "in add_iseq_to_process"); add_to_list(iseq->body->jit_unit, &unit_queue); if (active_units.length >= mjit_opts.max_cache_size) { - unload_units_p = true; + unload_requests++; } verbose(3, "Sending wakeup signal to workers in mjit_add_iseq_to_process"); rb_native_cond_broadcast(&mjit_worker_wakeup); diff --git a/mjit_worker.c b/mjit_worker.c index 426f1ac..6432785 100644 --- a/mjit_worker.c +++ b/mjit_worker.c @@ -225,8 +225,8 @@ static rb_nativethread_cond_t mjit_gc_wakeup; https://github.com/ruby/ruby/blob/trunk/mjit_worker.c#L225 static int in_gc = 0; // True when JIT is working. static bool in_jit = false; -// True when unload_units is requested from Ruby threads. -static bool unload_units_p = false; +// The times when unload_units is requested. unload_units is called after some requests. +static int unload_requests = 0; // Set to true to stop worker. static bool stop_worker_p; // Set to true if worker is stopped. @@ -910,9 +910,11 @@ compile_compact_jit_code(char* c_file) https://github.com/ruby/ruby/blob/trunk/mjit_worker.c#L910 bool iseq_gced = false; struct rb_mjit_unit *child_unit = 0; list_for_each(&active_units.head, child_unit, unode) { - if (child_unit->iseq == NULL) { + if (child_unit->iseq == NULL) { // ISeq is GC-ed iseq_gced = true; verbose(1, "JIT compaction: A method for JIT code u%d is obsoleted. Compaction will be skipped.", child_unit->id); + remove_from_list(child_unit, &active_units); + free_unit(child_unit); // unload it without waiting for throttled unload_units to retry compaction quickly } } in_jit = !iseq_gced; @@ -1331,6 +1333,10 @@ mjit_worker(void) https://github.com/ruby/ruby/blob/trunk/mjit_worker.c#L1333 int max_compact_size = mjit_opts.max_cache_size / 10; if (max_compact_size < 10) max_compact_size = 10; + // Run unload_units after it's requested `max_cache_size / 10` (default: 10) times. + // This throttles the call to mitigate locking in unload_units. + int unload_threshold = mjit_opts.max_cache_size / 10; + #ifndef _MSC_VER if (pch_status == PCH_NOT_READY) { make_pch(); @@ -1356,10 +1362,10 @@ mjit_worker(void) https://github.com/ruby/ruby/blob/trunk/mjit_worker.c#L1362 rb_native_cond_wait(&mjit_worker_wakeup, &mjit_engine_mutex); verbose(3, "Getting wakeup from client"); - if (unload_units_p) { + if (unload_requests >= unload_threshold) { RB_DEBUG_COUNTER_INC(mjit_unload_units); unload_units(); - unload_units_p = false; + unload_requests = 0; if (active_units.length == mjit_opts.max_cache_size && mjit_opts.wait) { // Sometimes all methods may be in use mjit_opts.max_cache_size++; // avoid infinite loop on `rb_mjit_wait_call`. Note that --jit-wait is just for testing. -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/