Skip to content

Commit 5c75612

Browse files
authored
Bump WasmKit to 0.1.0 (#17)
This improves mixed module rendering performance to due optimizations available in the latest version of WasmKit.
1 parent 8c5dfae commit 5c75612

File tree

8 files changed

+73
-69
lines changed

8 files changed

+73
-69
lines changed

ServerHost/Package.resolved

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ServerHost/Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ let package = Package(
2121
dependencies: [
2222
.package(url: "https://github.com/apple/swift-nio.git", from: "2.72.0"),
2323
.package(url: "https://github.com/apple/swift-system.git", from: "1.3.2"),
24-
.package(url: "https://github.com/swiftwasm/WasmKit.git", from: "0.0.8"),
24+
.package(url: "https://github.com/swiftwasm/WasmKit.git", from: "0.1.0"),
2525
.package(url: "https://github.com/hummingbird-project/hummingbird.git", from: "2.0.0"),
2626
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.3.0")
2727
],

ServerHost/Sources/Server/MixedOutput.swift

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -24,50 +24,54 @@ struct MixedOutput: ResponseGenerator {
2424

2525
func response(from request: Request, context: some RequestContext) throws -> Response {
2626
var samples = [Float32]()
27-
var memoryIndex = 0
2827

29-
let runtime = Runtime(
30-
hostModules: ["audio": .init(functions: [
31-
"encode": HostFunction(type: .init(
32-
parameters: [.i32, .i32, .i32]
33-
)) { caller, args in
34-
let start = args[1].i32
35-
let byteCount = args[2].i32
28+
let engine = Engine()
29+
let store = Store(engine: engine)
30+
var moduleInstances = [Instance]()
3631

37-
// Read audio buffer from Wasm linear memory.
38-
caller.runtime.store.memory(
39-
at: memoryIndex
40-
).data[Int(start)..<Int(start + byteCount)].withUnsafeBytes {
41-
// Rebind memory bytes to `Float`.
42-
$0.withMemoryRebound(to: Float.self) {
43-
// Enumerate each floating point sample
44-
for (i, sample) in $0.enumerated() {
45-
// Extend `samples` buffer if needed.
46-
if samples.count < $0.count {
47-
// 0.0 (no signal) is the default sample.
48-
samples.append(0.0)
49-
}
32+
// Instantiate each Wasm module
33+
for (moduleIndex, module) in modules.enumerated() {
34+
let encode = ExternalValue.function(.init(store: store, type: .init(
35+
parameters: [.i32, .i32, .i32]
36+
)) { caller, args in
37+
let start = args[1].i32
38+
let byteCount = args[2].i32
5039

51-
// Mix current sample with an existing value.
52-
samples[i] += sample
40+
// Read audio buffer from Wasm linear memory.
41+
moduleInstances[moduleIndex].exports[memory: "memory"]!.data[
42+
Int(start)..<Int(start + byteCount)
43+
].withUnsafeBytes {
44+
// Rebind memory bytes to `Float`.
45+
$0.withMemoryRebound(to: Float.self) {
46+
// Enumerate each floating point sample
47+
for (i, sample) in $0.enumerated() {
48+
// Extend `samples` buffer if needed.
49+
if samples.count < $0.count {
50+
// 0.0 (no signal) is the default sample.
51+
samples.append(0.0)
5352
}
5453

55-
assert(samples.count == $0.count)
54+
// Mix current sample with an existing value.
55+
samples[i] += sample
5656
}
57-
}
5857

59-
return []
58+
assert(samples.count == $0.count)
59+
}
6060
}
61-
])]
62-
)
6361

64-
// Instantiate each Wasm module
65-
for module in modules {
66-
let moduleInstance = try runtime.instantiate(module: module)
62+
return []
63+
})
64+
65+
let imports: Imports = [
66+
"audio": [ "encode": encode ]
67+
]
68+
let instance = try module.instantiate(store: store, imports: imports)
69+
moduleInstances.append(instance)
6770

6871
// Call entrypoint module function
69-
_ = try runtime.invoke(moduleInstance, function: "main", with: [.i32(0)])
70-
memoryIndex += 1
72+
73+
let main = instance.exports[function: "main"]!
74+
try main([.i32(0)])
7175
}
7276

7377
var body = ByteBuffer()

WATExample/Package.resolved

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

WATExample/Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ let package = Package(
77
name: "WasmHost",
88
platforms: [.macOS(.v14)],
99
dependencies: [
10-
.package(url: "https://github.com/swiftwasm/WasmKit.git", from: "0.0.8"),
10+
.package(url: "https://github.com/swiftwasm/WasmKit.git", from: "0.1.0"),
1111
],
1212
targets: [
1313
// Targets are the basic building blocks of a package, defining a module or a test suite.

WATExample/Sources/WATExample/main.swift

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,37 +15,35 @@ let binaryModule = try wat2wasm(String(decoding: Data(contentsOf: watURL), as: U
1515
// Parse as WasmKit IR.
1616
let parsedModule = try parseWasm(bytes: binaryModule)
1717

18+
let engine = Engine()
19+
let store = Store(engine: engine)
20+
1821
// Initialize WasmKit runtime
19-
let runtime = Runtime(
20-
hostModules: [
21-
"host": .init(
22-
functions: [
23-
// Pass host printer function as a closure
24-
"print": HostFunction(type: .init(parameters: [.i32, .i32])) { instance, args in
25-
guard let start = args.first?.i32,
26-
let offset = args.last?.i32
27-
else { return [] }
28-
29-
// Decode linear memory
30-
let string = String(
31-
decoding: instance.store
32-
.memory(at: 0)
33-
.data[Int(start) ..< Int(start + offset)],
34-
as: UTF8.self
35-
)
36-
37-
// Print the result
38-
print("Guest module printed: \(string)")
39-
return []
40-
},
41-
]
22+
let imports: Imports = [
23+
"host": [
24+
// Pass host printer function as a closure
25+
"print": ExternalValue.function(Function(store: store, type: .init(parameters: [.i32, .i32])) { caller, args in
26+
guard let start = args.first?.i32,
27+
let offset = args.last?.i32
28+
else { return [] }
29+
30+
// Decode linear memory
31+
let string = String(
32+
decoding: caller.instance!.exports[memory: "memory"]!.data[Int(start) ..< Int(start + offset)],
33+
as: UTF8.self
34+
)
35+
36+
// Print the result
37+
print("Guest module printed: \(string)")
38+
return []
39+
}
4240
),
4341
]
44-
)
42+
]
4543

4644
// Instantiate the module
47-
let moduleInstance = try runtime.instantiate(module: parsedModule)
45+
let moduleInstance = try parsedModule.instantiate(store: store, imports: imports)
4846

4947
// Call `main` function
50-
let result = try runtime.invoke(moduleInstance, function: "main")
48+
let result = try moduleInstance.exports[function: "main"]!()
5149
print("Returned value: \(result)")

WATExample/factorial-flat.wat

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
(func $print (param (; pointer ;) i32 (; length ;) i32)))
44
(export "main" (func $main))
55

6-
(memory 1)
6+
(memory $memory 1)
7+
(export "memory" (memory $memory))
78

89
;; n! = n * (n - 1) * (n - 2) * ... * 2 * 1
910
(func $factorial (param $arg i64) (result i64)

WATExample/factorial.wat

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
(func $print (param (; pointer ;) i32 (; length ;) i32)))
44
(export "main" (func $main))
55

6-
(memory 1)
6+
(memory $memory 1)
7+
(export "memory" (memory $memory))
78

89
;; n! = n * (n - 1) * (n - 2) * ... * 2 * 1
910
(func $factorial (param $arg i64) (result i64)

0 commit comments

Comments
 (0)