From ada01e34f43840e25957d29c1a7013fb0a153274 Mon Sep 17 00:00:00 2001 From: udo Date: Mon, 13 Jul 2026 08:07:37 +0000 Subject: [PATCH] Cache loaded source signatures safely --- scripts/test_dependency_invalidation.sh | 16 +++++++-- src/lib/compiler.cpp | 48 +++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/scripts/test_dependency_invalidation.sh b/scripts/test_dependency_invalidation.sh index d592443..25d318c 100755 --- a/scripts/test_dependency_invalidation.sh +++ b/scripts/test_dependency_invalidation.sh @@ -3,14 +3,24 @@ set -euo pipefail cd "$(dirname "$0")/.." test_name="dependency-cache-test-$$" -source_dir="site/$test_name" -cache_dir="${BIN_DIRECTORY:-/tmp/uce/work}$(pwd)/$source_dir" +site_directory="${UCE_TEST_SITE_DIRECTORY:-site}" +source_dir="$site_directory/$test_name" +bin_directory="${BIN_DIRECTORY:-}" +if [[ -z "$bin_directory" && -r /etc/uce/settings.cfg ]]; then + bin_directory=$(awk -F= '/^[[:space:]]*BIN_DIRECTORY[[:space:]]*=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2); print $2; exit}' /etc/uce/settings.cfg) +fi +bin_directory="${bin_directory:-/tmp/uce/work}" +cache_dir="" cleanup() { - rm -rf "$source_dir" "$cache_dir" + rm -rf "$source_dir" + if [[ -n "$cache_dir" ]]; then + rm -rf "$cache_dir" + fi } trap cleanup EXIT mkdir -p "$source_dir" +cache_dir="$bin_directory$(realpath "$source_dir")" printf '%s\n' \ '#ifndef UCE_DEPENDENCY_CACHE_CHILD' \ diff --git a/src/lib/compiler.cpp b/src/lib/compiler.cpp index c2934f1..c89bdbe 100644 --- a/src/lib/compiler.cpp +++ b/src/lib/compiler.cpp @@ -6,7 +6,9 @@ #include #include #include +#include #include +#include #include namespace { @@ -43,6 +45,19 @@ struct SharedUnitCompileCheck bool needs_compile = false; }; +struct UnitSourceSignatureEntry +{ + u64 modified_ns = 0; + u64 changed_ns = 0; + u64 size = 0; + String content_hash; + StringList loaded_paths; +}; + +const u64 UCE_UNIT_SOURCE_SIGNATURE_CACHE_MAX = 4096; +std::mutex unit_source_signature_cache_mutex; +std::map unit_source_signature_cache; + bool compiler_jit_compile_on_request_enabled(Request* context) { if(!context || !context->server) @@ -113,6 +128,33 @@ StringList compiler_unit_load_paths(String file_name, String content) return(paths); } +UnitSourceSignatureEntry compiler_unit_source_entry(String file_name) +{ + struct stat info; + UnitSourceSignatureEntry entry; + if(stat(file_name.c_str(), &info) != 0) + return(entry); + entry.modified_ns = (u64)info.st_mtim.tv_sec * 1000000000ull + (u64)info.st_mtim.tv_nsec; + entry.changed_ns = (u64)info.st_ctim.tv_sec * 1000000000ull + (u64)info.st_ctim.tv_nsec; + entry.size = (u64)info.st_size; + { + std::lock_guard lock(unit_source_signature_cache_mutex); + auto cached = unit_source_signature_cache.find(file_name); + if(cached != unit_source_signature_cache.end() && cached->second.modified_ns == entry.modified_ns && cached->second.changed_ns == entry.changed_ns && cached->second.size == entry.size) + return(cached->second); + } + String content = file_get_contents(file_name); + entry.content_hash = gen_sha1(content); + entry.loaded_paths = compiler_unit_load_paths(file_name, content); + { + std::lock_guard lock(unit_source_signature_cache_mutex); + if(unit_source_signature_cache.size() >= UCE_UNIT_SOURCE_SIGNATURE_CACHE_MAX) + unit_source_signature_cache.clear(); + unit_source_signature_cache[file_name] = entry; + } + return(entry); +} + void compiler_append_unit_source_signature(String file_name, std::set& visited, String& signature) { String normalized = path_real(file_name); @@ -122,9 +164,9 @@ void compiler_append_unit_source_signature(String file_name, std::set& v return; visited.insert(normalized); - String content = file_get_contents(file_name); - signature += normalized + ":" + gen_sha1(content) + "\n"; - for(String loaded : compiler_unit_load_paths(file_name, content)) + UnitSourceSignatureEntry entry = compiler_unit_source_entry(normalized); + signature += normalized + ":" + entry.content_hash + "\n"; + for(String loaded : entry.loaded_paths) compiler_append_unit_source_signature(loaded, visited, signature); }