From f7a245b2b6091ef3a5e1193423c7fbbd6fe6a538 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 15 Dec 2020 09:25:19 +0200 Subject: Cache more results of executing programs (compilers, etc) --- libbuild2/cc/guess.cxx | 20 +++--------- libbuild2/cc/module.cxx | 85 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 69 insertions(+), 36 deletions(-) (limited to 'libbuild2/cc') diff --git a/libbuild2/cc/guess.cxx b/libbuild2/cc/guess.cxx index 5a2e3b3..daa9d9b 100644 --- a/libbuild2/cc/guess.cxx +++ b/libbuild2/cc/guess.cxx @@ -2956,8 +2956,7 @@ namespace build2 // Compiler checks can be expensive (we often need to run the compiler // several times) so we cache the result. // - static map cache; - static mutex cache_mutex; + static global_cache cache; const compiler_info& guess (const char* xm, @@ -2988,11 +2987,8 @@ namespace build2 if (x_lo != nullptr) append_options (cs, *x_lo); key = cs.string (); - mlock l (cache_mutex); - - auto i (cache.find (key)); - if (i != cache.end ()) - return i->second; + if (const compiler_info* r = cache.find (key)) + return *r; } // Parse the user-specified compiler id (config.x.id). @@ -3144,15 +3140,7 @@ namespace build2 r.bin_pattern = p.directory ().representation (); // Trailing slash. } - // It's possible the cache entry already exists, in which case we - // ignore our value. - // - // But what if the compiler information it contains is different? Well, - // we don't generally deal with toolchain changes during the build so we - // ignore this special case as well. - // - mlock l (cache_mutex); - return cache.insert (make_pair (move (key), move (r))).first->second; + return cache.insert (move (key), move (r)); } strings diff --git a/libbuild2/cc/module.cxx b/libbuild2/cc/module.cxx index 14182a2..8241a01 100644 --- a/libbuild2/cc/module.cxx +++ b/libbuild2/cc/module.cxx @@ -338,6 +338,17 @@ namespace build2 # endif #endif + // Extracting search dirs can be expensive (we may need to run the + // compiler several times) so we cache the result. + // + struct search_dirs + { + pair lib; + pair inc; + }; + + static global_cache dirs_cache; + void config_module:: init (scope& rs, const location& loc, const variable_map&) { @@ -440,33 +451,67 @@ namespace build2 pair inc_dirs; const optional>& mod_dirs (xi.sys_mod_dirs); - if (xi.sys_lib_dirs) + if (xi.sys_lib_dirs && xi.sys_inc_dirs) + { lib_dirs = *xi.sys_lib_dirs; + inc_dirs = *xi.sys_inc_dirs; + } else { - switch (xi.class_) + string key; { - case compiler_class::gcc: - lib_dirs = gcc_library_search_dirs (xi.path, rs); - break; - case compiler_class::msvc: - lib_dirs = msvc_library_search_dirs (xi.path, rs); - break; + sha256 cs; + cs.append (static_cast (x_lang)); + cs.append (xi.path.effect_string ()); + append_options (cs, mode); + key = cs.string (); } - } - if (xi.sys_inc_dirs) - inc_dirs = *xi.sys_inc_dirs; - else - { - switch (xi.class_) + // Because the compiler info (xi) is also cached, we can assume that + // if dirs come from there, then they do so consistently. + // + const search_dirs* sd (dirs_cache.find (key)); + + if (xi.sys_lib_dirs) + lib_dirs = *xi.sys_lib_dirs; + else if (sd != nullptr) + lib_dirs = sd->lib; + else + { + switch (xi.class_) + { + case compiler_class::gcc: + lib_dirs = gcc_library_search_dirs (xi.path, rs); + break; + case compiler_class::msvc: + lib_dirs = msvc_library_search_dirs (xi.path, rs); + break; + } + } + + if (xi.sys_inc_dirs) + inc_dirs = *xi.sys_inc_dirs; + else if (sd != nullptr) + inc_dirs = sd->inc; + else + { + switch (xi.class_) + { + case compiler_class::gcc: + inc_dirs = gcc_header_search_dirs (xi.path, rs); + break; + case compiler_class::msvc: + inc_dirs = msvc_header_search_dirs (xi.path, rs); + break; + } + } + + if (sd == nullptr) { - case compiler_class::gcc: - inc_dirs = gcc_header_search_dirs (xi.path, rs); - break; - case compiler_class::msvc: - inc_dirs = msvc_header_search_dirs (xi.path, rs); - break; + search_dirs sd; + if (!xi.sys_lib_dirs) sd.lib = lib_dirs; + if (!xi.sys_inc_dirs) sd.inc = inc_dirs; + dirs_cache.insert (move (key), move (sd)); } } -- cgit v1.1