Cache loaded source signatures safely

This commit is contained in:
udo 2026-07-13 08:07:37 +00:00
parent 02ed75fc85
commit ada01e34f4
2 changed files with 58 additions and 6 deletions

View File

@ -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' \

View File

@ -6,7 +6,9 @@
#include <cctype>
#include <filesystem>
#include <fcntl.h>
#include <mutex>
#include <sys/file.h>
#include <sys/stat.h>
#include <unistd.h>
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<String, UnitSourceSignatureEntry> 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<std::mutex> 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<std::mutex> 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<String>& visited, String& signature)
{
String normalized = path_real(file_name);
@ -122,9 +164,9 @@ void compiler_append_unit_source_signature(String file_name, std::set<String>& 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);
}