diff options
author | Takashi Kokubun <[email protected]> | 2020-11-27 22:07:02 -0800 |
---|---|---|
committer | Takashi Kokubun <[email protected]> | 2020-11-27 22:26:14 -0800 |
commit | d80226e7bd801fcbccf71f19ba373b7baf71a49e (patch) | |
tree | 0568d8ba75118397c8ebe5bc4ffafa81039a187f /mjit_worker.c | |
parent | 12866b0d31755dc045d7c5fce0a61572a41891c7 (diff) |
Avoid unloading units which have enough total_calls
instead of just unloading worst 10% methods.
Diffstat (limited to 'mjit_worker.c')
-rw-r--r-- | mjit_worker.c | 44 |
1 files changed, 25 insertions, 19 deletions
diff --git a/mjit_worker.c b/mjit_worker.c index c708f01b63..426f1ace9f 100644 --- a/mjit_worker.c +++ b/mjit_worker.c @@ -1259,9 +1259,9 @@ static struct mjit_cont *first_cont; static void unload_units(void) { - struct rb_mjit_unit *unit = 0, *next, *worst; + struct rb_mjit_unit *unit = 0, *next; struct mjit_cont *cont; - int delete_num, units_num = active_units.length; + int units_num = active_units.length; // For now, we don't unload units when ISeq is GCed. We should // unload such ISeqs first here. @@ -1284,29 +1284,35 @@ unload_units(void) } // TODO: check stale_units and unload unused ones! (note that the unit is not associated to ISeq anymore) - // Remove 1/10 units more to decrease unloading calls. - // TODO: Calculate max total_calls in unit_queue and don't unload units - // whose total_calls are larger than the max. - delete_num = active_units.length / 10; - for (; active_units.length > mjit_opts.max_cache_size - delete_num;) { - // Find one unit that has the minimum total_calls. - worst = NULL; + // Unload units whose total_calls is smaller than any total_calls in unit_queue. + // TODO: make the algorithm more efficient + long unsigned prev_queue_calls = -1; + while (true) { + // Calculate the next max total_calls in unit_queue + long unsigned max_queue_calls = 0; + list_for_each(&unit_queue.head, unit, unode) { + if (unit->iseq != NULL && max_queue_calls < unit->iseq->body->total_calls + && unit->iseq->body->total_calls < prev_queue_calls) { + max_queue_calls = unit->iseq->body->total_calls; + } + } + prev_queue_calls = max_queue_calls; + + bool unloaded_p = false; list_for_each(&active_units.head, unit, unode) { if (unit->used_code_p) // We can't unload code on stack. continue; - if (worst == NULL || worst->iseq->body->total_calls > unit->iseq->body->total_calls) { - worst = unit; + if (max_queue_calls > unit->iseq->body->total_calls) { + verbose(2, "Unloading unit %d (calls=%lu, threshold=%lu)", + unit->id, unit->iseq->body->total_calls, max_queue_calls); + assert(unit->handle != NULL); + remove_from_list(unit, &active_units); + free_unit(unit); + unloaded_p = true; } } - if (worst == NULL) - break; - - // Unload the worst node. - verbose(2, "Unloading unit %d (calls=%lu)", worst->id, worst->iseq->body->total_calls); - assert(worst->handle != NULL); - remove_from_list(worst, &active_units); - free_unit(worst); + if (!unloaded_p) break; } if (units_num > active_units.length) { |