Skip to content

Commit 0e8a1c7

Browse files
committed
Only compile wasm once per process
1 parent ce3dd10 commit 0e8a1c7

File tree

2 files changed

+45
-38
lines changed

2 files changed

+45
-38
lines changed

internal/ext/wasm/runner.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
package wasm
22

3+
import "github.com/tetratelabs/wazero"
4+
35
type Runner struct {
46
URL string
57
SHA256 string
68
Env []string
9+
10+
rt wazero.Runtime
11+
code wazero.CompiledModule
712
}

internal/ext/wasm/wasm.go

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ import (
2929
"github.com/sqlc-dev/sqlc/internal/plugin"
3030
)
3131

32+
func NewRunner(url string, checksum string, env []string) *Runner {
33+
return &Runner{
34+
URL: url,
35+
SHA256: checksum,
36+
Env: env,
37+
rt: wazero.NewRuntime(context.Background()),
38+
}
39+
}
40+
3241
func cacheDir() (string, error) {
3342
cache := os.Getenv("SQLCCACHE")
3443
if cache != "" {
@@ -61,7 +70,7 @@ func (r *Runner) getChecksum(ctx context.Context) (string, error) {
6170
return sum, nil
6271
}
6372

64-
func (r *Runner) loadBytes(ctx context.Context) ([]byte, error) {
73+
func (r *Runner) loadAndCompile(ctx context.Context) (wazero.CompiledModule, error) {
6574
expected, err := r.getChecksum(ctx)
6675
if err != nil {
6776
return nil, err
@@ -71,14 +80,14 @@ func (r *Runner) loadBytes(ctx context.Context) ([]byte, error) {
7180
return nil, err
7281
}
7382
value, err, _ := flight.Do(expected, func() (interface{}, error) {
74-
return r.loadWASM(ctx, cacheDir, expected)
83+
return r.loadAndCompileWASM(ctx, cacheDir, expected)
7584
})
7685
if err != nil {
7786
return nil, err
7887
}
79-
data, ok := value.([]byte)
88+
data, ok := value.(wazero.CompiledModule)
8089
if !ok {
81-
return nil, fmt.Errorf("returned value was not a byte slice")
90+
return nil, fmt.Errorf("returned value was not a compiled module")
8291
}
8392
return data, nil
8493
}
@@ -124,7 +133,7 @@ func (r *Runner) fetch(ctx context.Context, uri string) ([]byte, string, error)
124133
return wmod, actual, nil
125134
}
126135

127-
func (r *Runner) loadWASM(ctx context.Context, cache string, expected string) ([]byte, error) {
136+
func (r *Runner) loadAndCompileWASM(ctx context.Context, cache string, expected string) (wazero.CompiledModule, error) {
128137
pluginDir := filepath.Join(cache, expected)
129138
pluginPath := filepath.Join(pluginDir, "plugin.wasm")
130139
_, staterr := os.Stat(pluginPath)
@@ -153,7 +162,22 @@ func (r *Runner) loadWASM(ctx context.Context, cache string, expected string) ([
153162
}
154163
}
155164

156-
return wmod, nil
165+
wazeroCache, err := wazero.NewCompilationCacheWithDir(filepath.Join(cache, "wazero"))
166+
if err != nil {
167+
return nil, fmt.Errorf("wazero.NewCompilationCacheWithDir: %w", err)
168+
}
169+
config := wazero.NewRuntimeConfig().WithCompilationCache(wazeroCache)
170+
r.rt = wazero.NewRuntimeWithConfig(ctx, config)
171+
// TODO: Handle error
172+
wasi_snapshot_preview1.MustInstantiate(ctx, r.rt)
173+
174+
// Compile the Wasm binary once so that we can skip the entire compilation time during instantiation.
175+
code, err := r.rt.CompileModule(ctx, wmod)
176+
if err != nil {
177+
return nil, fmt.Errorf("compile module: %w", err)
178+
}
179+
180+
return code, nil
157181
}
158182

159183
// removePGCatalog removes the pg_catalog schema from the request. There is a
@@ -195,47 +219,25 @@ func (r *Runner) Invoke(ctx context.Context, method string, args any, reply any,
195219
return fmt.Errorf("failed to encode codegen request: %w", err)
196220
}
197221

198-
cacheDir, err := cache.PluginsDir()
199-
if err != nil {
200-
return err
201-
}
202-
203-
cache, err := wazero.NewCompilationCacheWithDir(filepath.Join(cacheDir, "wazero"))
204-
if err != nil {
205-
return err
206-
}
207-
208-
wasmBytes, err := r.loadBytes(ctx)
209-
if err != nil {
210-
return fmt.Errorf("loadModule: %w", err)
211-
}
212-
213-
config := wazero.NewRuntimeConfig().WithCompilationCache(cache)
214-
rt := wazero.NewRuntimeWithConfig(ctx, config)
215-
defer rt.Close(ctx)
216-
217-
// TODO: Handle error
218-
wasi_snapshot_preview1.MustInstantiate(ctx, rt)
219-
220-
// Compile the Wasm binary once so that we can skip the entire compilation time during instantiation.
221-
mod, err := rt.CompileModule(ctx, wasmBytes)
222+
wasmCompiled, err := r.loadAndCompile(ctx)
222223
if err != nil {
223-
return err
224+
return fmt.Errorf("loadBytes: %w", err)
224225
}
225226

226227
var stderr, stdout bytes.Buffer
227228

228-
conf := wazero.NewModuleConfig()
229-
conf = conf.WithArgs("plugin.wasm", method)
230-
conf = conf.WithEnv("SQLC_VERSION", info.Version)
229+
conf := wazero.NewModuleConfig().
230+
WithName("").
231+
WithArgs("plugin.wasm", method).
232+
WithStdin(bytes.NewReader(stdinBlob)).
233+
WithStdout(&stdout).
234+
WithStderr(&stderr).
235+
WithEnv("SQLC_VERSION", info.Version)
231236
for _, key := range r.Env {
232237
conf = conf.WithEnv(key, os.Getenv(key))
233238
}
234-
conf = conf.WithStdin(bytes.NewReader(stdinBlob))
235-
conf = conf.WithStdout(&stdout)
236-
conf = conf.WithStderr(&stderr)
237239

238-
result, err := rt.InstantiateModule(ctx, mod, conf)
240+
result, err := r.rt.InstantiateModule(ctx, wasmCompiled, conf)
239241
if result != nil {
240242
defer result.Close(ctx)
241243
}

0 commit comments

Comments
 (0)