diff options
author | Jiyong Park <jiyong@google.com> | 2019-05-13 16:52:01 +0900 |
---|---|---|
committer | Jiyong Park <jiyong@google.com> | 2019-05-17 10:09:13 +0900 |
commit | 341b61e694a25e8e39250fd332e4b9eaecffc098 (patch) | |
tree | f39d095cf08b71a86bca1c9c1e729e629b0544c3 /linker/linker_utils.cpp | |
parent | b43f0b799365eab49c8f173fd3b6eef664e33e9d (diff) |
Don't resolve already resolved paths when parsing ld.config.txt
When parsing ld.config.txt, paths in *.search.paths properties are
resolved using resolved_paths(). This is causing a number of newfstatat
system calls during a process start-up and is contributing about 3.6%
of the entire linker initialization time.
Optimize the overhead by not resolving already resolved paths; resolved
paths are cached.
Bug: 132348336
Test: strace -C -e newfstatat ls shows the number of the syscalls is
reduced from 131 to 99
Test: simpleperf record --call-graph fp -f 10000000 -o /data/perf.data ls
simpleperf report -g -i /data/perf.data
shows percentage of get_paths() from 2.9% to 2.5%
Change-Id: I79823255a89f6e2a63b80c74e6768850276ab536
Diffstat (limited to 'linker/linker_utils.cpp')
-rw-r--r-- | linker/linker_utils.cpp | 77 |
1 files changed, 42 insertions, 35 deletions
diff --git a/linker/linker_utils.cpp b/linker/linker_utils.cpp index e92667157..29110ed56 100644 --- a/linker/linker_utils.cpp +++ b/linker/linker_utils.cpp @@ -204,47 +204,54 @@ void resolve_paths(std::vector<std::string>& paths, if (path.empty()) { continue; } + std::string resolved = resolve_path(path); + if (!resolved.empty()) { + resolved_paths->push_back(std::move(resolved)); + } + } +} - char resolved_path[PATH_MAX]; - const char* original_path = path.c_str(); - if (realpath(original_path, resolved_path) != nullptr) { - struct stat s; - if (stat(resolved_path, &s) == -1) { - DL_WARN("Warning: cannot stat file \"%s\": %s (ignoring)", resolved_path, strerror(errno)); - continue; - } - if (!S_ISDIR(s.st_mode)) { - DL_WARN("Warning: \"%s\" is not a directory (ignoring)", resolved_path); - continue; - } - resolved_paths->push_back(resolved_path); - } else { - std::string normalized_path; - if (!normalize_path(original_path, &normalized_path)) { - DL_WARN("Warning: unable to normalize \"%s\" (ignoring)", original_path); - continue; - } +std::string resolve_path(const std::string& path) { + char resolved_path[PATH_MAX]; + const char* original_path = path.c_str(); + if (realpath(original_path, resolved_path) != nullptr) { + struct stat s; + if (stat(resolved_path, &s) == -1) { + DL_WARN("Warning: cannot stat file \"%s\": %s (ignoring)", resolved_path, strerror(errno)); + return ""; + } + if (!S_ISDIR(s.st_mode)) { + DL_WARN("Warning: \"%s\" is not a directory (ignoring)", resolved_path); + return ""; + } + return resolved_path; + } else { + std::string normalized_path; + if (!normalize_path(original_path, &normalized_path)) { + DL_WARN("Warning: unable to normalize \"%s\" (ignoring)", original_path); + return ""; + } - std::string zip_path; - std::string entry_path; - if (parse_zip_path(normalized_path.c_str(), &zip_path, &entry_path)) { - if (realpath(zip_path.c_str(), resolved_path) == nullptr) { - DL_WARN("Warning: unable to resolve \"%s\": %s (ignoring)", - zip_path.c_str(), strerror(errno)); - continue; - } + std::string zip_path; + std::string entry_path; + if (parse_zip_path(normalized_path.c_str(), &zip_path, &entry_path)) { + if (realpath(zip_path.c_str(), resolved_path) == nullptr) { + DL_WARN("Warning: unable to resolve \"%s\": %s (ignoring)", + zip_path.c_str(), strerror(errno)); + return ""; + } - resolved_paths->push_back(std::string(resolved_path) + kZipFileSeparator + entry_path); - } else { - struct stat s; - if (stat(normalized_path.c_str(), &s) == 0 && S_ISDIR(s.st_mode)) { - // Path is not a zip path, but an existing directory. Then add it - // although we failed to resolve it. b/119656753 - resolved_paths->push_back(normalized_path); - } + return std::string(resolved_path) + kZipFileSeparator + entry_path; + } else { + struct stat s; + if (stat(normalized_path.c_str(), &s) == 0 && S_ISDIR(s.st_mode)) { + // Path is not a zip path, but an existing directory. Then add it + // although we failed to resolve it. b/119656753 + return normalized_path; } } } + return ""; } bool is_first_stage_init() { |