Skip to content

Commit a7ec7c9

Browse files
committed
perf: use wasmtime_instance_pre for zero-cost instantiation
Replace per-request wasmtime_linker_instantiate() with pre-validated wasmtime_instance_pre_t. Import resolution now happens once at module load time (vcl_init), not on every request. Changes: - Add instance_pre field to wasm_module_entry struct - Call wasmtime_linker_instantiate_pre() at load time (fail-fast) - Replace wasmtime_linker_instantiate() with wasmtime_instance_pre_instantiate() in both vwasm_engine_call() and vwasm_proxy_wasm_call() - Refactor find_module() to return entry pointer - Add cleanup of instance_pre in vwasm_engine_destroy() This eliminates ~50-100us of import resolution overhead per request while maintaining full isolation (fresh store per call).
1 parent 3b073d0 commit a7ec7c9

1 file changed

Lines changed: 26 additions & 14 deletions

File tree

src/wasm_engine.c

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
struct wasm_module_entry {
2929
char *name;
3030
wasmtime_module_t *module;
31+
wasmtime_instance_pre_t *instance_pre;
3132
};
3233

3334
struct vwasm_engine {
@@ -113,6 +114,7 @@ vwasm_engine_destroy(struct vwasm_engine **enginep)
113114

114115
for (i = 0; i < e->nmodules; i++) {
115116
free(e->modules[i].name);
117+
wasmtime_instance_pre_delete(e->modules[i].instance_pre);
116118
wasmtime_module_delete(e->modules[i].module);
117119
}
118120

@@ -282,6 +284,16 @@ vwasm_engine_load_module(struct vwasm_engine *engine,
282284
return (-1);
283285
}
284286

287+
/* Pre-instantiate: validate imports at load time (fail-fast) */
288+
error = wasmtime_linker_instantiate_pre(engine->linker, module,
289+
&engine->modules[engine->nmodules].instance_pre);
290+
if (error != NULL) {
291+
pthread_rwlock_unlock(&engine->rwlock);
292+
wasmtime_error_delete(error);
293+
wasmtime_module_delete(module);
294+
return (-1);
295+
}
296+
285297
engine->modules[engine->nmodules].name = strdup(name);
286298
engine->modules[engine->nmodules].module = module;
287299
engine->nmodules++;
@@ -291,14 +303,14 @@ vwasm_engine_load_module(struct vwasm_engine *engine,
291303
return (ret);
292304
}
293305

294-
static wasmtime_module_t *
306+
static struct wasm_module_entry *
295307
find_module(struct vwasm_engine *engine, const char *name)
296308
{
297309
int i;
298310

299311
for (i = 0; i < engine->nmodules; i++) {
300312
if (strcmp(engine->modules[i].name, name) == 0)
301-
return (engine->modules[i].module);
313+
return (&engine->modules[i]);
302314
}
303315
return (NULL);
304316
}
@@ -309,7 +321,7 @@ vwasm_engine_call(struct vwasm_engine *engine,
309321
const char *module_name, const char *func_name,
310322
int *result)
311323
{
312-
wasmtime_module_t *module;
324+
struct wasm_module_entry *entry;
313325
wasmtime_store_t *store;
314326
wasmtime_context_t *context;
315327
wasmtime_instance_t instance;
@@ -333,10 +345,10 @@ vwasm_engine_call(struct vwasm_engine *engine,
333345

334346
/* Find the pre-compiled module */
335347
pthread_rwlock_rdlock(&engine->rwlock);
336-
module = find_module(engine, module_name);
348+
entry = find_module(engine, module_name);
337349
pthread_rwlock_unlock(&engine->rwlock);
338350

339-
if (module == NULL)
351+
if (entry == NULL)
340352
return (-1);
341353

342354
/* Set up host context with Varnish request context */
@@ -357,9 +369,9 @@ vwasm_engine_call(struct vwasm_engine *engine,
357369
/* Set memory limiter — cap linear memory growth */
358370
wasmtime_store_limiter(store, (int64_t)mem_limit, -1, -1, -1, -1);
359371

360-
/* Instantiate the module via linker (resolves host function imports) */
361-
error = wasmtime_linker_instantiate(engine->linker, context,
362-
module, &instance, &trap);
372+
/* Instantiate from pre-validated instance (skips import resolution) */
373+
error = wasmtime_instance_pre_instantiate(entry->instance_pre,
374+
context, &instance, &trap);
363375
if (error != NULL) {
364376
log_error(ctx, error, module_name, func_name);
365377
goto cleanup;
@@ -498,7 +510,7 @@ vwasm_proxy_wasm_call(struct vwasm_engine *engine,
498510
const char *module_name,
499511
int *status_code)
500512
{
501-
wasmtime_module_t *module;
513+
struct wasm_module_entry *entry;
502514
wasmtime_store_t *store;
503515
wasmtime_context_t *context;
504516
wasmtime_instance_t instance;
@@ -526,10 +538,10 @@ vwasm_proxy_wasm_call(struct vwasm_engine *engine,
526538

527539
/* Find the pre-compiled module */
528540
pthread_rwlock_rdlock(&engine->rwlock);
529-
module = find_module(engine, module_name);
541+
entry = find_module(engine, module_name);
530542
pthread_rwlock_unlock(&engine->rwlock);
531543

532-
if (module == NULL)
544+
if (entry == NULL)
533545
return (-1);
534546

535547
/* Set up proxy-wasm context */
@@ -554,9 +566,9 @@ vwasm_proxy_wasm_call(struct vwasm_engine *engine,
554566
wasmtime_context_set_fuel(context, fuel_limit);
555567
wasmtime_store_limiter(store, (int64_t)mem_limit, -1, -1, -1, -1);
556568

557-
/* Instantiate the module via linker */
558-
error = wasmtime_linker_instantiate(engine->linker, context,
559-
module, &instance, &trap);
569+
/* Instantiate from pre-validated instance (skips import resolution) */
570+
error = wasmtime_instance_pre_instantiate(entry->instance_pre,
571+
context, &instance, &trap);
560572
if (error != NULL) {
561573
log_error(ctx, error, module_name, "instantiate");
562574
goto cleanup;

0 commit comments

Comments
 (0)