Skip to content

Commit 5a9cfe2

Browse files
committed
Add TinyGo JSON/Regex serialization benchmarks
- Create Dockerfile.tinygo template for TinyGo benchmarks - Add tinygo-json benchmark with encoding/json - Add tinygo-regex benchmark using standard library regexp
1 parent 8b83e79 commit 5a9cfe2

18 files changed

+233693
-0
lines changed

benchmarks/Dockerfile.tinygo

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
ARG TINYGO_VERSION=0.40.0
2+
FROM tinygo/tinygo:${TINYGO_VERSION}
3+
WORKDIR /home/tinygo
4+
ADD --chown=tinygo:tinygo go-benchmark go-benchmark
5+
WORKDIR /home/tinygo/go-benchmark
6+
RUN tinygo build -o benchmark.wasm -target=wasi .
7+
USER root
8+
RUN mkdir -p /benchmark && cp benchmark.wasm /benchmark/
9+
# We output the Wasm file to the `/benchmark` directory, where the client expects it.

benchmarks/all.suite

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ shootout/shootout-sieve.wasm
116116
shootout/shootout-switch.wasm
117117
shootout/shootout-xblabla20.wasm
118118
shootout/shootout-xchacha20.wasm
119+
tinygo/tinygo-json.wasm
120+
tinygo/tinygo-regex.wasm
119121
spidermonkey/benchmark.wasm
120122
tract-onnx-image-classification/benchmark.wasm
121123
richards/benchmark.wasm

benchmarks/tinygo.suite

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# TinyGo benchmarks - benchmarks compiled with TinyGo to WebAssembly.
2+
#
3+
# TinyGo is a Go compiler designed for small places, producing compact
4+
# WebAssembly binaries suitable for resource-constrained environments.
5+
6+
tinygo/tinygo-json.wasm
7+
tinygo/tinygo-regex.wasm

benchmarks/tinygo/Dockerfile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
ARG TINYGO_VERSION=0.40.0
2+
FROM tinygo/tinygo:${TINYGO_VERSION}
3+
4+
WORKDIR /usr/src
5+
6+
# Copy all benchmark source and build script
7+
COPY --chown=tinygo:tinygo json json
8+
COPY --chown=tinygo:tinygo regex regex
9+
COPY --chown=tinygo:tinygo build.sh .
10+
11+
# Create output directory as root and set permissions
12+
USER root
13+
RUN mkdir -p /benchmark && chown tinygo:tinygo /benchmark
14+
15+
# Switch back to tinygo user and build
16+
USER tinygo
17+
RUN OUTPUT_DIR=/benchmark ./build.sh
18+
19+
# Output goes to /benchmark where sightglass expects it

benchmarks/tinygo/README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# TinyGo Benchmarks
2+
3+
This directory contains multiple benchmarks compiled with TinyGo to WebAssembly.
4+
5+
TinyGo is a Go compiler designed for small places, producing compact
6+
WebAssembly binaries suitable for resource-constrained environments.
7+
8+
## Benchmarks
9+
10+
### tinygo-json.wasm
11+
JSON serialization and deserialization using Go's `encoding/json` package.
12+
- Input: ~2.1MB JSON file with 100 user records
13+
- Tests: Parse and stringify operations
14+
15+
### tinygo-regex.wasm
16+
Regular expression matching using Go's `regexp` package.
17+
- Input: ~6.5MB text corpus (same as `benchmarks/regex/default.input`)
18+
- Tests: 3 regex patterns (emails, URIs, IPs) matching the Rust benchmark
19+
20+
## Building
21+
22+
From the `benchmarks` directory:
23+
24+
```bash
25+
./build.sh tinygo/
26+
```
27+
28+
## Adding New Benchmarks
29+
30+
To add a new TinyGo benchmark, create a new directory containing `main.go`,
31+
`go.mod`, `default.input`, and expected output files. The build script will
32+
automatically discover and build it.

benchmarks/tinygo/build.sh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/bin/sh
2+
set -e
3+
4+
# Configuration
5+
TINYGO="${TINYGO:-tinygo}"
6+
OUTPUT_DIR="${OUTPUT_DIR:-$(pwd)}"
7+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8+
9+
# Create output directory if it doesn't exist
10+
mkdir -p "$OUTPUT_DIR"
11+
12+
cd "$SCRIPT_DIR"
13+
14+
# Auto-discover benchmarks: any directory with a main.go
15+
for dir in */; do
16+
# Remove trailing slash
17+
benchmark=$(basename "$dir")
18+
19+
# Skip if not a benchmark directory (no main.go)
20+
[ ! -f "$dir/main.go" ] && continue
21+
22+
echo "Building TinyGo $benchmark benchmark..."
23+
24+
cd "$dir"
25+
26+
# Build with TinyGo
27+
"$TINYGO" build -o "$OUTPUT_DIR/tinygo-$benchmark.wasm" -target=wasi .
28+
29+
cd "$SCRIPT_DIR"
30+
31+
echo "> Built tinygo-$benchmark.wasm"
32+
done
33+
34+
echo "All TinyGo benchmarks built successfully"

benchmarks/tinygo/json/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module benchmark
2+
3+
go 1.21

benchmarks/tinygo/json/main.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// TinyGo JSON serialization and deserialization benchmark.
2+
//
3+
// This benchmark tests JSON parsing and serialization performance using
4+
// the standard library encoding/json package.
5+
6+
package main
7+
8+
import (
9+
"encoding/json"
10+
"fmt"
11+
"os"
12+
)
13+
14+
// WASM imports for sightglass API
15+
//
16+
//go:wasm-module bench
17+
//export start
18+
func benchStart()
19+
20+
//go:wasm-module bench
21+
//export end
22+
func benchEnd()
23+
24+
// Data structures matching the Rust benchmark
25+
type User struct {
26+
ID uint64 `json:"id"`
27+
Username string `json:"username"`
28+
Email string `json:"email"`
29+
FullName string `json:"full_name"`
30+
IsActive bool `json:"is_active"`
31+
CreatedAt string `json:"created_at"`
32+
UpdatedAt string `json:"updated_at"`
33+
Profile Profile `json:"profile"`
34+
Settings Settings `json:"settings"`
35+
Posts []Post `json:"posts"`
36+
}
37+
38+
type Profile struct {
39+
Bio string `json:"bio"`
40+
AvatarURL string `json:"avatar_url"`
41+
Location string `json:"location"`
42+
Website *string `json:"website"`
43+
SocialLinks []string `json:"social_links"`
44+
}
45+
46+
type Settings struct {
47+
Theme string `json:"theme"`
48+
Language string `json:"language"`
49+
NotificationsEnabled bool `json:"notifications_enabled"`
50+
PrivacyLevel string `json:"privacy_level"`
51+
Preferences map[string]string `json:"preferences"`
52+
}
53+
54+
type Post struct {
55+
ID uint64 `json:"id"`
56+
Title string `json:"title"`
57+
Content string `json:"content"`
58+
Tags []string `json:"tags"`
59+
Likes uint32 `json:"likes"`
60+
CommentsCount uint32 `json:"comments_count"`
61+
PublishedAt string `json:"published_at"`
62+
}
63+
64+
func main() {
65+
// Read the JSON input file
66+
jsonData, err := os.ReadFile("tinygo-json.input")
67+
if err != nil {
68+
fmt.Fprintf(os.Stderr, "Error reading input: %v\n", err)
69+
os.Exit(1)
70+
}
71+
72+
benchStart()
73+
74+
// Deserialize: Parse JSON into structured data
75+
var users []User
76+
if err := json.Unmarshal(jsonData, &users); err != nil {
77+
fmt.Fprintf(os.Stderr, "Error parsing JSON: %v\n", err)
78+
os.Exit(1)
79+
}
80+
81+
// Serialize: Convert back to JSON
82+
serialized, err := json.Marshal(users)
83+
if err != nil {
84+
fmt.Fprintf(os.Stderr, "Error serializing JSON: %v\n", err)
85+
os.Exit(1)
86+
}
87+
88+
benchEnd()
89+
90+
fmt.Fprintf(os.Stderr, "[tinygo-json] processed %d users\n", len(users))
91+
fmt.Fprintf(os.Stderr, "[tinygo-json] serialized size: %d bytes\n", len(serialized))
92+
}

benchmarks/tinygo/regex/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module tinygo-regex
2+
3+
go 1.21

benchmarks/tinygo/regex/main.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// TinyGo regex benchmark.
2+
//
3+
// This benchmark tests regular expression matching performance using
4+
// the standard library regexp package.
5+
6+
package main
7+
8+
import (
9+
"fmt"
10+
"os"
11+
"regexp"
12+
)
13+
14+
// WASM imports for sightglass API
15+
//
16+
//go:wasm-module bench
17+
//export start
18+
func benchStart()
19+
20+
//go:wasm-module bench
21+
//export end
22+
func benchEnd()
23+
24+
func main() {
25+
// Read the input text file
26+
path := "tinygo-regex.input"
27+
fmt.Fprintf(os.Stderr, "[regex] matching %s\n", path)
28+
data, err := os.ReadFile(path)
29+
if err != nil {
30+
fmt.Fprintf(os.Stderr, "Error reading input: %v\n", err)
31+
os.Exit(1)
32+
}
33+
text := string(data)
34+
35+
// Use the same patterns as the Rust benchmark
36+
emailPattern := `[\w\.+-]+@[\w\.-]+\.[\w\.-]+`
37+
uriPattern := `[\w]+://[^/\s?#]+[^\s?#]+(?:\?[^\s#]*)?(?:#[^\s]*)?`
38+
ipPattern := `(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9])`
39+
40+
benchStart()
41+
42+
emails := countMatches(text, emailPattern)
43+
uris := countMatches(text, uriPattern)
44+
ips := countMatches(text, ipPattern)
45+
46+
benchEnd()
47+
48+
fmt.Fprintf(os.Stderr, "[regex] found %d emails\n", emails)
49+
fmt.Fprintf(os.Stderr, "[regex] found %d URIs\n", uris)
50+
fmt.Fprintf(os.Stderr, "[regex] found %d IPs\n", ips)
51+
}
52+
53+
func countMatches(text, pattern string) int {
54+
re := regexp.MustCompile(pattern)
55+
return len(re.FindAllString(text, -1))
56+
}

0 commit comments

Comments
 (0)