diff --git a/src/lib/compiler.cpp b/src/lib/compiler.cpp index ca45667..8f41199 100644 --- a/src/lib/compiler.cpp +++ b/src/lib/compiler.cpp @@ -3,6 +3,7 @@ #include "hash.h" #include #include +#include #include #include #include @@ -50,6 +51,7 @@ struct SharedUnitCompileCheck struct UnitSourceSignatureEntry { + std::chrono::steady_clock::time_point checked_at; u64 modified_ns = 0; u64 changed_ns = 0; u64 size = 0; @@ -144,12 +146,22 @@ bool compiler_source_readable(String file_name, const struct stat& info, int* re return(error == 0); } -UnitSourceSignatureEntry compiler_unit_source_entry(String file_name) +UnitSourceSignatureEntry compiler_unit_source_entry(String file_name, bool allow_recent_stat) { + auto checked_at = std::chrono::steady_clock::now(); + if(allow_recent_stat) + { + 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() && + std::chrono::duration_cast(checked_at - cached->second.checked_at).count() < 1000) + return(cached->second); + } struct stat info; UnitSourceSignatureEntry entry; if(stat(file_name.c_str(), &info) != 0) return(entry); + entry.checked_at = checked_at; 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; @@ -158,7 +170,10 @@ UnitSourceSignatureEntry compiler_unit_source_entry(String file_name) 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 && cached->second.readable == entry.readable) + { + cached->second.checked_at = checked_at; return(cached->second); + } } String content = file_get_contents(file_name); entry.content_hash = gen_sha1(content); @@ -172,7 +187,7 @@ UnitSourceSignatureEntry compiler_unit_source_entry(String file_name) return(entry); } -void compiler_append_unit_source_signature(String file_name, std::set& visited, String& signature) +void compiler_append_unit_source_signature(String file_name, std::set& visited, String& signature, bool allow_recent_stat) { String normalized = path_real(file_name); if(normalized == "") @@ -181,28 +196,28 @@ void compiler_append_unit_source_signature(String file_name, std::set& v return; visited.insert(normalized); - UnitSourceSignatureEntry entry = compiler_unit_source_entry(normalized); + UnitSourceSignatureEntry entry = compiler_unit_source_entry(normalized, allow_recent_stat); signature += normalized + ":" + entry.content_hash + (entry.readable ? String("") : String(":unreadable")) + "\n"; for(String loaded : entry.loaded_paths) - compiler_append_unit_source_signature(loaded, visited, signature); + compiler_append_unit_source_signature(loaded, visited, signature, allow_recent_stat); } -String compiler_unit_source_signature(String file_name) +String compiler_unit_source_signature(String file_name, bool allow_recent_stat = false) { std::set visited; String signature = "uce-load-graph-v1\n"; - compiler_append_unit_source_signature(file_name, visited, signature); + compiler_append_unit_source_signature(file_name, visited, signature, allow_recent_stat); return(gen_sha1(signature)); } -String compiler_unit_input_signature(Request* context, SharedUnit* su) +String compiler_unit_input_signature(Request* context, SharedUnit* su, bool allow_recent_source_stat = false) { if(!context || !su || !file_exists(su->file_name)) return(""); String setup_template = context->server->config["COMPILER_SYS_PATH"] + "/" + context->server->config["SETUP_TEMPLATE"]; return( - compiler_unit_source_signature(su->file_name) + ":" + + compiler_unit_source_signature(su->file_name, allow_recent_source_stat) + ":" + gen_sha1(file_get_contents(setup_template)) + ":" + std::to_string(UCE_UNIT_ABI_VERSION) ); @@ -452,7 +467,7 @@ bool compiler_has_known_unit_cached(Request* context, String file_name) })); } -SharedUnitFilesystemState inspect_shared_unit_filesystem(Request* context, SharedUnit* su) +SharedUnitFilesystemState inspect_shared_unit_filesystem(Request* context, SharedUnit* su, bool allow_recent_source_stat = false) { SharedUnitFilesystemState state; state.source_exists = file_exists(su->file_name); @@ -465,7 +480,7 @@ SharedUnitFilesystemState inspect_shared_unit_filesystem(Request* context, Share state.compiler_abi_time = compiler_runtime_abi_time(context); state.metadata_time = file_mtime(su->meta_file_name); state.compile_output_time = file_mtime(su->compile_output_file_name); - state.current_input_signature = compiler_unit_input_signature(context, su); + state.current_input_signature = compiler_unit_input_signature(context, su, allow_recent_source_stat); state.metadata_exists = (state.metadata_time != 0); state.compile_output_exists = (state.compile_output_time != 0); if(state.metadata_exists) @@ -1301,12 +1316,12 @@ void compiler_untrack_known_unit(Request* context, String file_name) }); } -bool compiler_unit_needs_recompile(Request* context, String file_name, bool* source_missing) +bool compiler_unit_needs_recompile(Request* context, String file_name, bool* source_missing, bool allow_recent_source_stat) { file_name = compiler_normalize_unit_path(context, file_name); SharedUnit su; setup_unit_paths(context, &su, file_name); - auto state = inspect_shared_unit_filesystem(context, &su); + auto state = inspect_shared_unit_filesystem(context, &su, allow_recent_source_stat); auto compile_check = shared_unit_compile_check(state); if(source_missing) *source_missing = compile_check.source_missing; diff --git a/src/lib/compiler.h b/src/lib/compiler.h index 327a520..8e84725 100644 --- a/src/lib/compiler.h +++ b/src/lib/compiler.h @@ -27,7 +27,7 @@ StringList compiler_list_known_units(Request* context); void compiler_set_known_units(Request* context, StringList files); void compiler_track_known_unit(Request* context, String file_name); void compiler_untrack_known_unit(Request* context, String file_name); -bool compiler_unit_needs_recompile(Request* context, String file_name, bool* source_missing = 0); +bool compiler_unit_needs_recompile(Request* context, String file_name, bool* source_missing = 0, bool allow_recent_source_stat = false); DValue unit_info(String path = ""); StringList units_list(); bool unit_compile(String path = ""); diff --git a/src/wasm/worker.cpp b/src/wasm/worker.cpp index 9ab964c..2bb27d5 100644 --- a/src/wasm/worker.cpp +++ b/src/wasm/worker.cpp @@ -2210,7 +2210,7 @@ private: now - cached_freshness->second.checked_at).count() >= 1000; if(check_freshness) { - stale = compiler_unit_needs_recompile(context, resolved, 0); + stale = compiler_unit_needs_recompile(context, resolved, 0, can_serve_stale && read_request); worker.component_freshness[resolved] = { now, stale }; } else