Reduce startup time on Windows by using std::filesystem::canonical

realpath() apparently doesn't handle Windows symlinks very well. This
causes plugin::Manager and ScannedFile to rescan a bunch of extra
paths that they should be skipping. This commit reduces the startup
time on Windows by 3-4 seconds (~8.5s to ~5s).
This commit is contained in:
Tim Wojtulewicz 2023-01-18 13:10:33 -07:00 committed by Tim Wojtulewicz
parent d6ce5894a7
commit db161bd6df
4 changed files with 17 additions and 14 deletions

View file

@ -21,14 +21,13 @@ ScannedFile::ScannedFile(int arg_include_level, std::string arg_name, bool arg_s
canonical_path = canonical_stdin_path;
else
{
char buf[PATH_MAX];
auto res = realpath(name.data(), buf);
std::error_code ec;
auto canon = filesystem::canonical(name, ec);
if ( ec )
zeek::reporter->FatalError("failed to get canonical path of %s: %s", name.data(),
ec.message().c_str());
if ( ! res )
zeek::reporter->FatalError("failed to get realpath() of %s: %s", name.data(),
strerror(errno));
canonical_path = res;
canonical_path = canon.string();
}
}

View file

@ -12,7 +12,7 @@ namespace zeek::detail
{
// Script file we have already scanned (or are in the process of scanning).
// They are identified by normalized realpath.
// They are identified by normalized canonical path.
class ScannedFile
{
@ -30,7 +30,7 @@ public:
bool skipped; // This ScannedFile was @unload'd.
bool prefixes_checked; // If loading prefixes for this file has been tried.
std::string name;
std::string canonical_path; // normalized, absolute path via realpath()
std::string canonical_path; // normalized, absolute path via std::filesystem::canonical()
static auto constexpr canonical_stdin_path = "<stdin>";
};

View file

@ -76,14 +76,17 @@ void Manager::SearchDynamicPlugins(const std::string& dir)
return;
}
char canon_path[PATH_MAX];
if ( ! realpath(dir.data(), canon_path) )
std::error_code ec;
auto canon = filesystem::canonical(dir, ec);
if ( ec )
{
DBG_LOG(DBG_PLUGINS, "skip dynamic plugin search in %s, realpath failed: %s", dir.data(),
strerror(errno));
DBG_LOG(DBG_PLUGINS, "skip dynamic plugin search in %s, making path canonical failed: %s",
dir.data(), ec.message().c_str());
return;
}
std::string canon_path = canon.string();
if ( searched_dirs.count(canon_path) )
return;

View file

@ -482,7 +482,8 @@ private:
// Directories that have already been searched for dynamic plugins.
// Used to prevent multiple searches of the same dirs (e.g. via symlinks).
// The paths stored in the set are made canonical via realpath().
// The paths stored in the set are made canonical via calls to
// std::filesystem::canonical().
std::set<std::string, std::less<>> searched_dirs;
// Plugins that were explicitly requested to be activated, but failed to