From 53a8c6b690ea771be2fcb08bebef8dd564665c20 Mon Sep 17 00:00:00 2001 From: Maofeng Date: Thu, 30 Jul 2026 07:18:21 +0800 Subject: [PATCH] feat(runtime): cache compiled components Enable Wasmtime's persistent compilation cache and expose an optional cache directory in RuntimeConfig. Create and canonicalize the configured directory before Engine construction, and report cache filesystem and configuration failures through dedicated RuntimeError variants. --- Cargo.lock | 118 ++++++++++++++++++++++---- Cargo.toml | 2 +- crates/wasmeld-runtime/src/error.rs | 12 ++- crates/wasmeld-runtime/src/runtime.rs | 21 ++++- 4 files changed, 132 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 394379d..2dfd579 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -673,7 +673,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" dependencies = [ - "thiserror", + "thiserror 2.0.19", ] [[package]] @@ -1042,6 +1042,27 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "directories-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "displaydoc" version = "0.2.6" @@ -1937,7 +1958,7 @@ dependencies = [ "jni-sys", "log", "simd_cesu8", - "thiserror", + "thiserror 2.0.19", "walkdir", "windows-link", ] @@ -2057,6 +2078,15 @@ dependencies = [ "cc", ] +[[package]] +name = "libredox" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +dependencies = [ + "libc", +] + [[package]] name = "linkme" version = "0.3.37" @@ -2654,7 +2684,7 @@ dependencies = [ "rustc-hash 2.1.3", "rustls", "socket2", - "thiserror", + "thiserror 2.0.19", "tokio", "tracing", "web-time", @@ -2677,7 +2707,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror", + "thiserror 2.0.19", "tinyvec", "tracing", "web-time", @@ -2856,6 +2886,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 1.0.69", +] + [[package]] name = "regalloc2" version = "0.13.5" @@ -3582,7 +3623,7 @@ dependencies = [ "tantivy-stacker", "tantivy-tokenizer-api", "tempfile", - "thiserror", + "thiserror 2.0.19", "time", "typetag", "uuid", @@ -3718,13 +3759,33 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + [[package]] name = "thiserror" version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.19", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] @@ -4084,7 +4145,7 @@ checksum = "050686193eb999b4bb3bc2acfa891a13da00f79734704c4b8b4ef1a10b368a3c" dependencies = [ "crossbeam-channel", "symlink", - "thiserror", + "thiserror 2.0.19", "time", "tracing-subscriber", ] @@ -4152,7 +4213,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b6c49aecd4abae3ffa88ab1e28b3de7a7497a9732be828e3a6f1855b6ea80fd" dependencies = [ "mimalloc", - "thiserror", + "thiserror 2.0.19", "tracing", "tracing-subscriber", "turso_core", @@ -4219,7 +4280,7 @@ dependencies = [ "strum_macros", "tantivy", "tempfile", - "thiserror", + "thiserror 2.0.19", "tracing", "tracing-subscriber", "turso_ext", @@ -4264,7 +4325,7 @@ dependencies = [ "miette", "strum", "strum_macros", - "thiserror", + "thiserror 2.0.19", "turso_macros", ] @@ -4312,7 +4373,7 @@ dependencies = [ "roaring", "serde", "serde_json", - "thiserror", + "thiserror 2.0.19", "tracing", "turso_core", "turso_parser", @@ -4645,7 +4706,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "thiserror", + "thiserror 2.0.19", "toasty", "toasty-driver-turso", "tokio", @@ -4668,7 +4729,7 @@ dependencies = [ "serde_json", "sha2", "tempfile", - "thiserror", + "thiserror 2.0.19", "toml", "wit-component 0.243.0", "wit-parser 0.243.0", @@ -4680,7 +4741,7 @@ name = "wasmeld-runtime" version = "0.1.0" dependencies = [ "serde", - "thiserror", + "thiserror 2.0.19", "toml", "wasmeld-package", "wasmtime", @@ -4755,6 +4816,7 @@ dependencies = [ "target-lexicon", "wasmparser 0.243.0", "wasmtime-environ", + "wasmtime-internal-cache", "wasmtime-internal-component-macro", "wasmtime-internal-component-util", "wasmtime-internal-cranelift", @@ -4794,6 +4856,26 @@ dependencies = [ "wasmtime-internal-component-util", ] +[[package]] +name = "wasmtime-internal-cache" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a31a582632f47753e4a9a5412ab5edfbc05a6df9031336a2f2eff46a70a1cac" +dependencies = [ + "base64 0.22.1", + "directories-next", + "log", + "postcard", + "rustix 1.1.4", + "serde", + "serde_derive", + "sha2", + "toml", + "wasmtime-environ", + "windows-sys 0.61.2", + "zstd", +] + [[package]] name = "wasmtime-internal-component-macro" version = "41.0.0" @@ -4834,7 +4916,7 @@ dependencies = [ "pulley-interpreter", "smallvec", "target-lexicon", - "thiserror", + "thiserror 2.0.19", "wasmparser 0.243.0", "wasmtime-environ", "wasmtime-internal-math", @@ -4969,7 +5051,7 @@ dependencies = [ "io-lifetimes", "rustix 1.1.4", "system-interface", - "thiserror", + "thiserror 2.0.19", "tokio", "tracing", "url", @@ -5076,7 +5158,7 @@ dependencies = [ "regalloc2", "smallvec", "target-lexicon", - "thiserror", + "thiserror 2.0.19", "wasmparser 0.243.0", "wasmtime-environ", "wasmtime-internal-cranelift", @@ -5540,7 +5622,7 @@ dependencies = [ "flate2", "indexmap", "memchr", - "thiserror", + "thiserror 2.0.19", "zopfli", ] diff --git a/Cargo.toml b/Cargo.toml index fcec5ea..db8af12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ toml = "0.9.8" tower-http = { version = "0.7.0", features = ["cors", "trace"] } tracing = "0.1.44" tracing-subscriber = { version = "0.3.23", features = ["env-filter", "fmt"] } -wasmtime = { version = "=41.0.0", default-features = false, features = ["component-model", "cranelift", "runtime", "std"] } +wasmtime = { version = "=41.0.0", default-features = false, features = ["cache", "component-model", "cranelift", "runtime", "std"] } wasmtime-wasi = { version = "=41.0.0", default-features = false, features = ["p2"] } wit-bindgen = "=0.41.0" wit-component = "=0.243.0" diff --git a/crates/wasmeld-runtime/src/error.rs b/crates/wasmeld-runtime/src/error.rs index 4b22831..1a56e12 100644 --- a/crates/wasmeld-runtime/src/error.rs +++ b/crates/wasmeld-runtime/src/error.rs @@ -1,6 +1,6 @@ //! Runtime error taxonomy exposed to management layers. -use std::time::Duration; +use std::{path::PathBuf, time::Duration}; use thiserror::Error; @@ -36,6 +36,16 @@ pub enum RuntimeError { #[error("runtime creation failed: {0}")] RuntimeCreation(#[source] wasmtime::Error), + #[error("failed to prepare Component compilation cache {path}: {source}")] + CacheDirectory { + path: PathBuf, + #[source] + source: std::io::Error, + }, + + #[error("invalid Component compilation cache configuration: {0}")] + CacheConfiguration(#[source] wasmtime::Error), + #[error("failed to read component artifact {path}: {source}")] ArtifactRead { path: String, diff --git a/crates/wasmeld-runtime/src/runtime.rs b/crates/wasmeld-runtime/src/runtime.rs index 6322273..3560485 100644 --- a/crates/wasmeld-runtime/src/runtime.rs +++ b/crates/wasmeld-runtime/src/runtime.rs @@ -8,6 +8,7 @@ use std::{ collections::HashMap, fs, + path::PathBuf, sync::{ Arc, Mutex, atomic::{AtomicBool, Ordering}, @@ -18,7 +19,7 @@ use std::{ }; use wasmtime::{ - Config, Engine, Store, StoreLimits, StoreLimitsBuilder, + Cache, CacheConfig, Config, Engine, Store, StoreLimits, StoreLimitsBuilder, component::{Component, HasData, Linker, ResourceTable}, }; use wasmtime_wasi::{ @@ -61,6 +62,8 @@ pub struct RuntimeConfig { pub epoch_tick: Duration, /// Maximum native stack reservation for WebAssembly execution. pub max_wasm_stack: usize, + /// Optional persistent cache for compiled Component machine code. + pub component_cache_dir: Option, /// Service-scoped storage used by Components importing the KV capability. pub kv_backend: Option>, } @@ -70,6 +73,7 @@ impl Default for RuntimeConfig { Self { epoch_tick: DEFAULT_EPOCH_TICK, max_wasm_stack: DEFAULT_MAX_WASM_STACK, + component_cache_dir: None, kv_backend: None, } } @@ -180,6 +184,21 @@ impl Runtime { wasmtime_config.consume_fuel(true); wasmtime_config.epoch_interruption(true); wasmtime_config.max_wasm_stack(config.max_wasm_stack); + if let Some(cache_dir) = &config.component_cache_dir { + fs::create_dir_all(cache_dir).map_err(|source| RuntimeError::CacheDirectory { + path: cache_dir.clone(), + source, + })?; + let cache_dir = + fs::canonicalize(cache_dir).map_err(|source| RuntimeError::CacheDirectory { + path: cache_dir.clone(), + source, + })?; + let mut cache_config = CacheConfig::new(); + cache_config.with_directory(cache_dir); + let cache = Cache::new(cache_config).map_err(RuntimeError::CacheConfiguration)?; + wasmtime_config.cache(Some(cache)); + } let engine = Arc::new(Engine::new(&wasmtime_config).map_err(RuntimeError::RuntimeCreation)?);