From 32b41e5c60be45997e37b1ff879bc426bd00f15e Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Wed, 4 Mar 2026 09:22:47 -0400 Subject: [PATCH] Optimise I/O during indexing Signed-off-by: Juan Cruz Viotti --- src/build/adapter_filesystem.cc | 81 +++++++++++++++++++-------------- src/index/index.cc | 5 +- src/index/output.h | 3 +- 3 files changed, 50 insertions(+), 39 deletions(-) diff --git a/src/build/adapter_filesystem.cc b/src/build/adapter_filesystem.cc index bead7581..4aae8669 100644 --- a/src/build/adapter_filesystem.cc +++ b/src/build/adapter_filesystem.cc @@ -3,8 +3,9 @@ #include #include // assert -#include // std::ofstream +#include // std::ofstream, std::ifstream #include // std::unique_lock +#include // std::string #include // std::string_view namespace sourcemeta::one { @@ -25,45 +26,55 @@ auto BuildAdapterFilesystem::read_dependencies(const node_type &path) const -> std::optional> { assert(path.is_absolute()); const auto dependencies_path{this->dependencies_path(path)}; - if (std::filesystem::exists(dependencies_path)) { - auto stream{sourcemeta::core::read_file(dependencies_path)}; - assert(stream.is_open()); - - BuildDependencies result; - std::string line; - while (std::getline(stream, line)) { - // Prevent CRLF on Windows - if (!line.empty() && line.back() == '\r') { - line.pop_back(); - } - if (!line.empty()) { - auto kind{BuildDependencyKind::Static}; - std::filesystem::path dependency; - if (line.size() >= 2 && line[1] == ' ' && - (line[0] == 's' || line[0] == 'd')) { - kind = (line[0] == 'd') ? BuildDependencyKind::Dynamic - : BuildDependencyKind::Static; - dependency = line.substr(2); - } else { - dependency = line; - } - if (!dependency.is_absolute()) { - dependency = - std::filesystem::weakly_canonical(this->root / dependency); - } - - result.emplace_back(kind, std::move(dependency)); - } + std::ifstream stream{dependencies_path}; + if (!stream.is_open()) { + return std::nullopt; + } + + std::string contents{std::istreambuf_iterator(stream), + std::istreambuf_iterator()}; + + BuildDependencies result; + std::size_t position{0}; + while (position < contents.size()) { + auto newline{contents.find('\n', position)}; + if (newline == std::string::npos) { + newline = contents.size(); } - if (result.empty()) { - return std::nullopt; - } else { - return result; + auto end{newline}; + // Prevent CRLF on Windows + if (end > position && contents[end - 1] == '\r') { + end -= 1; } - } else { + + if (end > position) { + auto kind{BuildDependencyKind::Static}; + std::filesystem::path dependency; + const auto length{end - position}; + if (length >= 2 && contents[position + 1] == ' ' && + (contents[position] == 's' || contents[position] == 'd')) { + kind = (contents[position] == 'd') ? BuildDependencyKind::Dynamic + : BuildDependencyKind::Static; + dependency = contents.substr(position + 2, end - position - 2); + } else { + dependency = contents.substr(position, length); + } + if (!dependency.is_absolute()) { + dependency = (this->root / dependency).lexically_normal(); + } + + result.emplace_back(kind, std::move(dependency)); + } + + position = newline + 1; + } + + if (result.empty()) { return std::nullopt; + } else { + return result; } } diff --git a/src/index/index.cc b/src/index/index.cc index 3e6d32af..cb039904 100644 --- a/src/index/index.cc +++ b/src/index/index.cc @@ -550,8 +550,9 @@ static auto index_main(const std::string_view &program, const auto relative_path{std::filesystem::relative(entry, schemas_path)}; print_progress(mutex, 1, "Producing", relative_path.string(), cursor + 1, directories.size()); - const auto destination{std::filesystem::weakly_canonical( - explorer_path / relative_path / SENTINEL / "directory.metapack")}; + const auto destination{ + (explorer_path / relative_path / SENTINEL / "directory.metapack") + .lexically_normal()}; DISPATCH( destination, // If any of the entry summary files changes, by definition we need to diff --git a/src/index/output.h b/src/index/output.h index 384876f4..62e97874 100644 --- a/src/index/output.h +++ b/src/index/output.h @@ -16,8 +16,7 @@ namespace sourcemeta::one { class Output { public: - Output(std::filesystem::path path) - : path_{std::filesystem::weakly_canonical(path)} { + Output(std::filesystem::path path) : path_{path.lexically_normal()} { std::filesystem::create_directories(this->path_); for (const auto &entry : std::filesystem::recursive_directory_iterator(this->path_)) {