Skip to content

Commit 539fd44

Browse files
Build benchmarks with PackageToJS
1 parent 0f1fdd1 commit 539fd44

28 files changed

+720
-1841
lines changed

Diff for: .github/workflows/perf.yml

-21
This file was deleted.

Diff for: Benchmarks/Package.swift

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// swift-tools-version: 6.0
2+
3+
import PackageDescription
4+
5+
let package = Package(
6+
name: "Benchmarks",
7+
dependencies: [
8+
.package(path: "../")
9+
],
10+
targets: [
11+
.executableTarget(
12+
name: "Benchmarks",
13+
dependencies: ["JavaScriptKit"],
14+
exclude: ["Generated/JavaScript", "bridge.d.ts"],
15+
swiftSettings: [
16+
.enableExperimentalFeature("Extern")
17+
]
18+
)
19+
]
20+
)

Diff for: Benchmarks/README.md

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# JavaScriptKit Benchmarks
2+
3+
This directory contains performance benchmarks for JavaScriptKit.
4+
5+
## Building Benchmarks
6+
7+
Before running the benchmarks, you need to build the test suite:
8+
9+
```bash
10+
JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --swift-sdk $SWIFT_SDK_ID js -c release
11+
```
12+
13+
## Running Benchmarks
14+
15+
```bash
16+
# Run with default settings
17+
node run.js
18+
19+
# Save results to a JSON file
20+
node run.js --output=results.json
21+
22+
# Specify number of iterations
23+
node run.js --runs=20
24+
25+
# Run in adaptive mode until results stabilize
26+
node run.js --adaptive --output=stable-results.json
27+
28+
# Run benchmarks and compare with previous results
29+
node run.js --baseline=previous-results.json
30+
```

Diff for: Benchmarks/Sources/Benchmarks.swift

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import JavaScriptKit
2+
3+
class Benchmark {
4+
init(_ title: String) {
5+
self.title = title
6+
}
7+
8+
let title: String
9+
10+
func testSuite(_ name: String, _ body: @escaping () -> Void) {
11+
let jsBody = JSClosure { arguments -> JSValue in
12+
body()
13+
return .undefined
14+
}
15+
benchmarkRunner("\(title)/\(name)", jsBody)
16+
}
17+
}
18+
19+
@JS func run() {
20+
21+
let call = Benchmark("Call")
22+
23+
call.testSuite("JavaScript function call through Wasm import") {
24+
for _ in 0..<20_000_000 {
25+
benchmarkHelperNoop()
26+
}
27+
}
28+
29+
call.testSuite("JavaScript function call through Wasm import with int") {
30+
for _ in 0..<10_000_000 {
31+
benchmarkHelperNoopWithNumber(42)
32+
}
33+
}
34+
35+
let propertyAccess = Benchmark("Property access")
36+
37+
do {
38+
let swiftInt: Double = 42
39+
let object = JSObject()
40+
object.jsNumber = JSValue.number(swiftInt)
41+
propertyAccess.testSuite("Write Number") {
42+
for _ in 0..<1_000_000 {
43+
object.jsNumber = JSValue.number(swiftInt)
44+
}
45+
}
46+
}
47+
48+
do {
49+
let object = JSObject()
50+
object.jsNumber = JSValue.number(42)
51+
propertyAccess.testSuite("Read Number") {
52+
for _ in 0..<1_000_000 {
53+
_ = object.jsNumber.number
54+
}
55+
}
56+
}
57+
58+
do {
59+
let swiftString = "Hello, world"
60+
let object = JSObject()
61+
object.jsString = swiftString.jsValue
62+
propertyAccess.testSuite("Write String") {
63+
for _ in 0..<1_000_000 {
64+
object.jsString = swiftString.jsValue
65+
}
66+
}
67+
}
68+
69+
do {
70+
let object = JSObject()
71+
object.jsString = JSValue.string("Hello, world")
72+
propertyAccess.testSuite("Read String") {
73+
for _ in 0..<1_000_000 {
74+
_ = object.jsString.string
75+
}
76+
}
77+
}
78+
}

Diff for: Benchmarks/Sources/Generated/ExportSwift.swift

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit,
2+
// DO NOT EDIT.
3+
//
4+
// To update this file, just rebuild your project or run
5+
// `swift package bridge-js`.
6+
@_extern(wasm, module: "bjs", name: "return_string")
7+
private func _return_string(_ ptr: UnsafePointer<UInt8>?, _ len: Int32)
8+
@_extern(wasm, module: "bjs", name: "init_memory")
9+
private func _init_memory(_ sourceId: Int32, _ ptr: UnsafeMutablePointer<UInt8>?)
10+
11+
@_expose(wasm, "bjs_main")
12+
@_cdecl("bjs_main")
13+
public func _bjs_main() -> Void {
14+
main()
15+
}

Diff for: Benchmarks/Sources/Generated/ImportTS.swift

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit,
2+
// DO NOT EDIT.
3+
//
4+
// To update this file, just rebuild your project or run
5+
// `swift package bridge-js`.
6+
7+
@_spi(JSObject_id) import JavaScriptKit
8+
9+
@_extern(wasm, module: "bjs", name: "make_jsstring")
10+
private func _make_jsstring(_ ptr: UnsafePointer<UInt8>?, _ len: Int32) -> Int32
11+
12+
@_extern(wasm, module: "bjs", name: "init_memory_with_result")
13+
private func _init_memory_with_result(_ ptr: UnsafePointer<UInt8>?, _ len: Int32)
14+
15+
@_extern(wasm, module: "bjs", name: "free_jsobject")
16+
private func _free_jsobject(_ ptr: Int32) -> Void
17+
18+
func benchmarkHelperNoop() -> Void {
19+
@_extern(wasm, module: "Benchmarks", name: "bjs_benchmarkHelperNoop")
20+
func bjs_benchmarkHelperNoop() -> Void
21+
bjs_benchmarkHelperNoop()
22+
}
23+
24+
func benchmarkHelperNoopWithNumber(_ n: Double) -> Void {
25+
@_extern(wasm, module: "Benchmarks", name: "bjs_benchmarkHelperNoopWithNumber")
26+
func bjs_benchmarkHelperNoopWithNumber(_ n: Float64) -> Void
27+
bjs_benchmarkHelperNoopWithNumber(n)
28+
}
29+
30+
func benchmarkRunner(_ name: String, _ body: JSObject) -> Void {
31+
@_extern(wasm, module: "Benchmarks", name: "bjs_benchmarkRunner")
32+
func bjs_benchmarkRunner(_ name: Int32, _ body: Int32) -> Void
33+
var name = name
34+
let nameId = name.withUTF8 { b in
35+
_make_jsstring(b.baseAddress.unsafelyUnwrapped, Int32(b.count))
36+
}
37+
bjs_benchmarkRunner(nameId, Int32(bitPattern: body.id))
38+
}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"classes" : [
3+
4+
],
5+
"functions" : [
6+
{
7+
"abiName" : "bjs_main",
8+
"name" : "main",
9+
"parameters" : [
10+
11+
],
12+
"returnType" : {
13+
"void" : {
14+
15+
}
16+
}
17+
}
18+
]
19+
}
+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
{
2+
"children" : [
3+
{
4+
"functions" : [
5+
{
6+
"name" : "benchmarkHelperNoop",
7+
"parameters" : [
8+
9+
],
10+
"returnType" : {
11+
"void" : {
12+
13+
}
14+
}
15+
},
16+
{
17+
"name" : "benchmarkHelperNoopWithNumber",
18+
"parameters" : [
19+
{
20+
"name" : "n",
21+
"type" : {
22+
"double" : {
23+
24+
}
25+
}
26+
}
27+
],
28+
"returnType" : {
29+
"void" : {
30+
31+
}
32+
}
33+
},
34+
{
35+
"name" : "benchmarkRunner",
36+
"parameters" : [
37+
{
38+
"name" : "name",
39+
"type" : {
40+
"string" : {
41+
42+
}
43+
}
44+
},
45+
{
46+
"name" : "body",
47+
"type" : {
48+
"jsObject" : {
49+
50+
}
51+
}
52+
}
53+
],
54+
"returnType" : {
55+
"void" : {
56+
57+
}
58+
}
59+
}
60+
],
61+
"types" : [
62+
63+
]
64+
}
65+
],
66+
"moduleName" : "Benchmarks"
67+
}

Diff for: Benchmarks/Sources/bridge.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
declare function benchmarkHelperNoop(): void;
2+
declare function benchmarkHelperNoopWithNumber(n: number): void;
3+
declare function benchmarkRunner(name: string, body: (n: number) => void): void;

Diff for: Benchmarks/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ "type": "module" }

0 commit comments

Comments
 (0)