[model-gateway] Optimize WASM cache lookups using SHA-256 (#17344)
This commit is contained in:
@@ -143,7 +143,7 @@ impl WasmModuleManager {
|
|||||||
let start_time = std::time::Instant::now();
|
let start_time = std::time::Instant::now();
|
||||||
|
|
||||||
// First, get the WASM bytes with a read lock (faster)
|
// First, get the WASM bytes with a read lock (faster)
|
||||||
let wasm_bytes = {
|
let (wasm_bytes, wasm_hash) = {
|
||||||
let modules = self
|
let modules = self
|
||||||
.modules
|
.modules
|
||||||
.read()
|
.read()
|
||||||
@@ -153,7 +153,10 @@ impl WasmModuleManager {
|
|||||||
.ok_or_else(|| WasmError::from(WasmManagerError::ModuleNotFound(module_uuid)))?;
|
.ok_or_else(|| WasmError::from(WasmManagerError::ModuleNotFound(module_uuid)))?;
|
||||||
|
|
||||||
// Clone the pre-loaded WASM bytes (already in memory, no file I/O)
|
// Clone the pre-loaded WASM bytes (already in memory, no file I/O)
|
||||||
module.module_meta.wasm_bytes.clone()
|
(
|
||||||
|
module.module_meta.wasm_bytes.clone(),
|
||||||
|
module.module_meta.sha256_hash,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -179,7 +182,7 @@ impl WasmModuleManager {
|
|||||||
|
|
||||||
let result = self
|
let result = self
|
||||||
.runtime
|
.runtime
|
||||||
.execute_component_async(wasm_bytes, attach_point, input)
|
.execute_component_async(wasm_bytes, wasm_hash, attach_point, input)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Record metrics
|
// Record metrics
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ pub struct WasmThreadPool {
|
|||||||
pub enum WasmTask {
|
pub enum WasmTask {
|
||||||
ExecuteComponent {
|
ExecuteComponent {
|
||||||
wasm_bytes: Vec<u8>,
|
wasm_bytes: Vec<u8>,
|
||||||
|
wasm_hash: [u8; 32],
|
||||||
attach_point: WasmModuleAttachPoint,
|
attach_point: WasmModuleAttachPoint,
|
||||||
input: WasmComponentInput,
|
input: WasmComponentInput,
|
||||||
response: oneshot::Sender<Result<WasmComponentOutput>>,
|
response: oneshot::Sender<Result<WasmComponentOutput>>,
|
||||||
@@ -108,6 +109,7 @@ impl WasmRuntime {
|
|||||||
pub async fn execute_component_async(
|
pub async fn execute_component_async(
|
||||||
&self,
|
&self,
|
||||||
wasm_bytes: Vec<u8>,
|
wasm_bytes: Vec<u8>,
|
||||||
|
wasm_hash: [u8; 32],
|
||||||
attach_point: WasmModuleAttachPoint,
|
attach_point: WasmModuleAttachPoint,
|
||||||
input: WasmComponentInput,
|
input: WasmComponentInput,
|
||||||
) -> Result<WasmComponentOutput> {
|
) -> Result<WasmComponentOutput> {
|
||||||
@@ -116,6 +118,7 @@ impl WasmRuntime {
|
|||||||
|
|
||||||
let task = WasmTask::ExecuteComponent {
|
let task = WasmTask::ExecuteComponent {
|
||||||
wasm_bytes,
|
wasm_bytes,
|
||||||
|
wasm_hash,
|
||||||
attach_point,
|
attach_point,
|
||||||
input,
|
input,
|
||||||
response: response_tx,
|
response: response_tx,
|
||||||
@@ -281,7 +284,7 @@ impl WasmThreadPool {
|
|||||||
|
|
||||||
let cache_capacity =
|
let cache_capacity =
|
||||||
NonZeroUsize::new(config.module_cache_size).unwrap_or(NonZeroUsize::new(10).unwrap());
|
NonZeroUsize::new(config.module_cache_size).unwrap_or(NonZeroUsize::new(10).unwrap());
|
||||||
let mut component_cache: LruCache<Vec<u8>, Component> = LruCache::new(cache_capacity);
|
let mut component_cache: LruCache<[u8; 32], Component> = LruCache::new(cache_capacity);
|
||||||
|
|
||||||
// Start epoch incrementer for timeout enforcement.
|
// Start epoch incrementer for timeout enforcement.
|
||||||
// The engine's epoch counter is incremented periodically, and each Store
|
// The engine's epoch counter is incremented periodically, and each Store
|
||||||
@@ -320,6 +323,7 @@ impl WasmThreadPool {
|
|||||||
match task {
|
match task {
|
||||||
WasmTask::ExecuteComponent {
|
WasmTask::ExecuteComponent {
|
||||||
wasm_bytes,
|
wasm_bytes,
|
||||||
|
wasm_hash,
|
||||||
attach_point,
|
attach_point,
|
||||||
input,
|
input,
|
||||||
response,
|
response,
|
||||||
@@ -328,6 +332,7 @@ impl WasmThreadPool {
|
|||||||
&engine,
|
&engine,
|
||||||
&mut component_cache, // Pass the cache
|
&mut component_cache, // Pass the cache
|
||||||
wasm_bytes,
|
wasm_bytes,
|
||||||
|
wasm_hash,
|
||||||
attach_point,
|
attach_point,
|
||||||
input,
|
input,
|
||||||
&config,
|
&config,
|
||||||
@@ -342,28 +347,29 @@ impl WasmThreadPool {
|
|||||||
|
|
||||||
async fn execute_component_in_worker(
|
async fn execute_component_in_worker(
|
||||||
engine: &Engine,
|
engine: &Engine,
|
||||||
cache: &mut LruCache<Vec<u8>, Component>, // cache argument
|
cache: &mut LruCache<[u8; 32], Component>, // cache argument
|
||||||
wasm_bytes: Vec<u8>,
|
wasm_bytes: Vec<u8>,
|
||||||
|
wasm_hash: [u8; 32],
|
||||||
attach_point: WasmModuleAttachPoint,
|
attach_point: WasmModuleAttachPoint,
|
||||||
input: WasmComponentInput,
|
input: WasmComponentInput,
|
||||||
config: &WasmRuntimeConfig,
|
config: &WasmRuntimeConfig,
|
||||||
) -> Result<WasmComponentOutput> {
|
) -> Result<WasmComponentOutput> {
|
||||||
// Compile component from bytes OR retrieve from cache
|
// Compile component from bytes OR retrieve from cache
|
||||||
// Note: The WASM file must be in component format (not plain WASM module)
|
// Note: The WASM file must be in component format (not plain WASM module)
|
||||||
let component = if let Some(comp) = cache.get(&wasm_bytes) {
|
let component = if let Some(comp) = cache.get(&wasm_hash) {
|
||||||
comp.clone() // Component is just a handle (cheap clone)
|
comp.clone() // Component is just a handle (cheap clone)
|
||||||
} else {
|
} else {
|
||||||
// Compile new component
|
// Compile new component
|
||||||
let comp = Component::new(engine, &wasm_bytes).map_err(|e| {
|
let comp = Component::new(engine, &wasm_bytes).map_err(|e| {
|
||||||
WasmRuntimeError::CompileFailed(format!(
|
WasmError::Runtime(WasmRuntimeError::CompileFailed(format!(
|
||||||
"failed to parse WebAssembly component: {}. \
|
"failed to parse WebAssembly component: {}. \
|
||||||
Hint: The WASM file must be in component format. \
|
Hint: The WASM file must be in component format. \
|
||||||
If you're using wit-bindgen, use 'wasm-tools component new' to wrap the WASM module into a component.",
|
If you're using wit-bindgen, use 'wasm-tools component new' to wrap the WASM module into a component.",
|
||||||
e
|
e
|
||||||
))
|
)))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
cache.push(wasm_bytes, comp.clone());
|
cache.push(wasm_hash, comp.clone());
|
||||||
comp
|
comp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user