-
Notifications
You must be signed in to change notification settings - Fork 243
/
stars.go
100 lines (87 loc) · 2.82 KB
/
stars.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package main
import (
"context"
"io"
"log"
"net/http"
"os"
"path"
"path/filepath"
"strings"
"time"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/experimental"
gojs "github.com/tetratelabs/wazero/imports/go"
"github.com/tetratelabs/wazero/sys"
)
// main invokes Wasm compiled via `GOARCH=wasm GOOS=js`, which reports the star
// count of wazero.
//
// This shows how to integrate an HTTP client with wasm using gojs.
func main() {
// The Wasm binary (stars/main.wasm) is very large (>7.5MB). Use wazero's
// compilation cache to reduce performance penalty of multiple runs.
compilationCacheDir := ".build"
ctx, err := experimental.WithCompilationCacheDirName(context.Background(), compilationCacheDir)
if err != nil {
log.Panicln(err)
}
// Create a new WebAssembly Runtime.
r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfig().
// WebAssembly 2.0 allows use of gojs.
WithWasmCore2())
defer r.Close(ctx) // This closes everything this Runtime created.
// Combine the above into our baseline config, overriding defaults.
config := wazero.NewModuleConfig().
// By default, I/O streams are discarded, so you won't see output.
WithStdout(os.Stdout).WithStderr(os.Stderr)
bin, err := os.ReadFile(path.Join("stars", "main.wasm"))
if err != nil {
log.Panicln(err)
}
// Compile the WebAssembly module using the default configuration.
start := time.Now()
compiled, err := r.CompileModule(ctx, bin, wazero.NewCompileConfig())
if err != nil {
log.Panicln(err)
}
compilationTime := time.Since(start).Milliseconds()
log.Printf("CompileModule took %dms with %dKB cache", compilationTime, dirSize(compilationCacheDir)/1024)
// Instead of making real HTTP calls, return fake data.
ctx = gojs.WithRoundTripper(ctx, &fakeGitHub{})
// Execute the "run" function, which corresponds to "main" in stars/main.go.
start = time.Now()
err = gojs.Run(ctx, r, compiled, config)
runTime := time.Since(start).Milliseconds()
log.Printf("gojs.Run took %dms", runTime)
if exitErr, ok := err.(*sys.ExitError); ok && exitErr.ExitCode() != 0 {
log.Panicln(err)
} else if !ok {
log.Panicln(err)
}
}
// compile-time check to ensure fakeGitHub implements http.RoundTripper
var _ http.RoundTripper = &fakeGitHub{}
type fakeGitHub struct{}
func (f *fakeGitHub) RoundTrip(*http.Request) (*http.Response, error) {
fakeResponse := `{"stargazers_count": 9999999}`
return &http.Response{
StatusCode: http.StatusOK,
Status: http.StatusText(http.StatusOK),
Body: io.NopCloser(strings.NewReader(fakeResponse)),
ContentLength: int64(len(fakeResponse)),
}, nil
}
func dirSize(dir string) int64 {
var size int64
_ = filepath.Walk(dir, func(_ string, info os.FileInfo, err error) error {
if err != nil {
log.Panicln(err)
}
if !info.IsDir() {
size += info.Size()
}
return nil
})
return size
}