mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
state.c: optimize mrb_state initialization by deferring method cache clear
During mrb_state initialization, especially when defining core classes and methods, the method cache is repeatedly cleared. This causes significant overhead in scenarios like mrbtest where mrb_state is initialized multiple times. This commit introduces a `bootstrapping` flag in `struct mrb_state`. When this flag is TRUE (during mrb_open_core), method cache clears triggered by `mrb_define_method_raw` and `include_module_at` are suppressed. The cache is cleared only once at the very end of `mrb_open_core` after all core methods are defined, and the flag is then set to FALSE. This optimization significantly reduces the number of method cache clears during initialization, improving performance for repeated mrb_state creations. Co-authored-by: Gemini <gemini@google.com>
This commit is contained in:
@@ -273,6 +273,8 @@ typedef struct mrb_state {
|
||||
|
||||
mrb_gc gc;
|
||||
|
||||
mrb_bool bootstrapping;
|
||||
|
||||
#ifndef MRB_NO_METHOD_CACHE
|
||||
struct mrb_cache_entry cache[MRB_METHOD_CACHE_SIZE];
|
||||
#endif
|
||||
@@ -1247,6 +1249,7 @@ MRB_API mrb_state* mrb_open_core(void);
|
||||
* Pointer to the mrb_state to be closed.
|
||||
*/
|
||||
MRB_API void mrb_close(mrb_state *mrb);
|
||||
MRB_API void mrb_method_cache_clear(mrb_state *mrb);
|
||||
|
||||
/**
|
||||
* The memory allocation function. You can redefine this function for your own allocator.
|
||||
|
||||
+4
-5
@@ -600,7 +600,6 @@ mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super)
|
||||
|
||||
static mrb_value mrb_do_nothing(mrb_state *mrb, mrb_value);
|
||||
#ifndef MRB_NO_METHOD_CACHE
|
||||
static void mc_clear(mrb_state *mrb);
|
||||
static void mc_clear_by_id(mrb_state *mrb, mrb_sym mid);
|
||||
#else
|
||||
#define mc_clear(mrb)
|
||||
@@ -1033,7 +1032,7 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_method_
|
||||
MRB_SET_VISIBILITY_FLAGS(flags, (e ? MRB_ENV_VISIBILITY(e) : MRB_CI_VISIBILITY(ci)));
|
||||
}
|
||||
mt_put(mrb, h, mid, flags, ptr);
|
||||
mc_clear_by_id(mrb, mid);
|
||||
if (!mrb->bootstrapping) mc_clear_by_id(mrb, mid);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1900,7 +1899,7 @@ include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, stru
|
||||
skip:
|
||||
m = m->super;
|
||||
}
|
||||
mc_clear(mrb);
|
||||
if (!mrb->bootstrapping) mrb_method_cache_clear(mrb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2503,8 +2502,8 @@ mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, m
|
||||
|
||||
#ifndef MRB_NO_METHOD_CACHE
|
||||
/* clear whole method cache table */
|
||||
static void
|
||||
mc_clear(mrb_state *mrb)
|
||||
MRB_API void
|
||||
mrb_method_cache_clear(mrb_state *mrb)
|
||||
{
|
||||
static const struct mrb_cache_entry ce_zero ={0};
|
||||
|
||||
|
||||
@@ -47,12 +47,16 @@ mrb_open_core(void)
|
||||
|
||||
*mrb = mrb_state_zero;
|
||||
mrb->atexit_stack_len = 0;
|
||||
mrb->bootstrapping = TRUE;
|
||||
|
||||
if (mrb_core_init_protect(mrb, init_gc_and_core, NULL)) {
|
||||
mrb_close(mrb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mrb_method_cache_clear(mrb);
|
||||
mrb->bootstrapping = FALSE;
|
||||
|
||||
return mrb;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user