Reset autoloads in response to variable changes

Prior to this fix, autoloads like function and completion autoloads
would check their path variable (like fish_function_path) on every
autoload request. Switch to invalidating it in response to the variable
changing.

This improves time on a microbenchmark:

    for i in (seq 50000)
      setenv test_env val$i
    end

from ~11 seconds to ~6.5 seconds.
This commit is contained in:
ridiculousfish
2018-02-15 21:58:02 -08:00
parent be13ac353b
commit 9cd952588f
7 changed files with 44 additions and 19 deletions

View File

@@ -65,19 +65,10 @@ int autoload_t::load(const wcstring &cmd, bool reload) {
CHECK_BLOCK(0);
ASSERT_IS_MAIN_THREAD();
auto path_var = env_get(env_var_name);
// Do we know where to look?
if (path_var.missing_or_empty()) return 0;
// Check if the lookup path has changed. If so, drop all loaded files.
if (*path_var != this->last_path) {
this->last_path = *path_var;
this->last_path_tokenized.clear();
this->last_path.to_list(this->last_path_tokenized);
scoped_lock locker(lock);
this->evict_all_nodes();
if (!this->paths) {
auto path_var = env_get(env_var_name);
if (path_var.missing_or_empty()) return 0;
this->paths = path_var->as_list();
}
// Mark that we're loading this. Hang onto the iterator for fast erasing later. Note that
@@ -98,7 +89,8 @@ int autoload_t::load(const wcstring &cmd, bool reload) {
return 1;
}
// Try loading it.
res = this->locate_file_and_maybe_load_it(cmd, true, reload, this->last_path_tokenized);
assert(paths && "Should have paths");
res = this->locate_file_and_maybe_load_it(cmd, true, reload, *this->paths);
// Clean up.
is_loading_set.erase(where);
return res;
@@ -113,6 +105,13 @@ bool autoload_t::can_load(const wcstring &cmd, const env_vars_snapshot_t &vars)
return this->locate_file_and_maybe_load_it(cmd, false, false, path_list);
}
void autoload_t::invalidate() {
ASSERT_IS_MAIN_THREAD();
scoped_lock locker(lock);
paths.reset();
this->evict_all_nodes();
}
/// Check whether the given command is loaded.
bool autoload_t::has_tried_loading(const wcstring &cmd) {
scoped_lock locker(lock);