From: Joel Rosdahl Date: Sun, 29 Jan 2023 12:12:30 +0000 (+0100) Subject: fix: Cache path relativization in preprocessed output X-Git-Tag: v4.8~40 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=147ea804a27afe96899a2f9fe010b91faa3eacc5;p=thirdparty%2Fccache.git fix: Cache path relativization in preprocessed output After PR #1033 and [1], a stat call is made each time a note about an include file is found in the preprocessed output. Such calls are very performant on Linux (and therefore unnoticed until now), but apparently costly on Windows. Fix this by caching the calculation of relative paths in process_preprocessed_file. [1]: 9a05332915d2808f4713437006b3f7c812d9fd74 Closes #1245. --- diff --git a/src/Util.cpp b/src/Util.cpp index 8f6b4102c..e1b0d865d 100644 --- a/src/Util.cpp +++ b/src/Util.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2019-2022 Joel Rosdahl and other contributors +// Copyright (C) 2019-2023 Joel Rosdahl and other contributors // // See doc/AUTHORS.adoc for a complete list of contributors. // @@ -980,7 +980,8 @@ std::string normalize_concrete_absolute_path(const std::string& path) { const auto normalized_path = normalize_abstract_absolute_path(path); - return Stat::stat(normalized_path).same_inode_as(Stat::stat(path)) + return (normalized_path == path + || Stat::stat(normalized_path).same_inode_as(Stat::stat(path))) ? normalized_path : path; } diff --git a/src/ccache.cpp b/src/ccache.cpp index 5179d8d3a..c26133a07 100644 --- a/src/ccache.cpp +++ b/src/ccache.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2002-2007 Andrew Tridgell -// Copyright (C) 2009-2022 Joel Rosdahl and other contributors +// Copyright (C) 2009-2023 Joel Rosdahl and other contributors // // See doc/AUTHORS.adoc for a complete list of contributors. // @@ -74,6 +74,7 @@ #include #include #include +#include using core::Statistic; @@ -457,6 +458,8 @@ process_preprocessed_file(Context& ctx, Hash& hash, const std::string& path) return nonstd::make_unexpected(Statistic::internal_error); } + std::unordered_map relative_inc_path_cache; + // Bytes between p and q are pending to be hashed. char* q = &(*data)[0]; const char* p = q; @@ -559,10 +562,18 @@ process_preprocessed_file(Context& ctx, Hash& hash, const std::string& path) } r++; } + // p and q span the include file path. std::string inc_path(p, q - p); - inc_path = Util::normalize_concrete_absolute_path(inc_path); - inc_path = Util::make_relative_path(ctx, inc_path); + auto it = relative_inc_path_cache.find(inc_path); + if (it == relative_inc_path_cache.end()) { + auto rel_inc_path = Util::make_relative_path( + ctx, Util::normalize_concrete_absolute_path(inc_path)); + relative_inc_path_cache.emplace(inc_path, rel_inc_path); + inc_path = std::move(rel_inc_path); + } else { + inc_path = it->second; + } if ((inc_path != ctx.apparent_cwd) || ctx.config.hash_dir()) { hash.hash(inc_path);