Skip to content

Commit e30a452

Browse files
authored
Merge pull request #73 from maraf/DotnetWasm
Add .NET on WebAssembly workload
2 parents 8c28a5f + 5aa9dad commit e30a452

File tree

81 files changed

+37582
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+37582
-0
lines changed

JetStreamDriver.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,6 +1507,32 @@ class WasmLegacyBenchmark extends Benchmark {
15071507
}
15081508
};
15091509

1510+
function dotnetPreloads(type)
1511+
{
1512+
return {
1513+
dotnetUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/dotnet.js`,
1514+
dotnetNativeUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/dotnet.native.js`,
1515+
dotnetRuntimeUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/dotnet.runtime.js`,
1516+
wasmBinaryUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/dotnet.native.wasm`,
1517+
icuCustomUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/icudt_CJK.dat`,
1518+
dllCollectionsConcurrentUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/System.Collections.Concurrent.wasm`,
1519+
dllCollectionsUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/System.Collections.wasm`,
1520+
dllComponentModelPrimitivesUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/System.ComponentModel.Primitives.wasm`,
1521+
dllComponentModelTypeConverterUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/System.ComponentModel.TypeConverter.wasm`,
1522+
dllDrawingPrimitivesUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/System.Drawing.Primitives.wasm`,
1523+
dllDrawingUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/System.Drawing.wasm`,
1524+
dllIOPipelinesUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/System.IO.Pipelines.wasm`,
1525+
dllLinqUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/System.Linq.wasm`,
1526+
dllMemoryUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/System.Memory.wasm`,
1527+
dllObjectModelUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/System.ObjectModel.wasm`,
1528+
dllPrivateCorelibUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/System.Private.CoreLib.wasm`,
1529+
dllRuntimeInteropServicesJavaScriptUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/System.Runtime.InteropServices.JavaScript.wasm`,
1530+
dllTextEncodingsWebUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/System.Text.Encodings.Web.wasm`,
1531+
dllTextJsonUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/System.Text.Json.wasm`,
1532+
dllAppUrl: `./wasm/dotnet/build-${type}/wwwroot/_framework/dotnet.wasm`,
1533+
}
1534+
}
1535+
15101536
let BENCHMARKS = [
15111537
// ARES
15121538
new DefaultBenchmark({
@@ -2212,6 +2238,29 @@ let BENCHMARKS = [
22122238
iterations: 40,
22132239
tags: ["Wasm"],
22142240
}),
2241+
// .NET
2242+
new AsyncBenchmark({
2243+
name: "dotnet-interp",
2244+
files: [
2245+
"./wasm/dotnet/interp.js",
2246+
"./wasm/dotnet/benchmark.js",
2247+
],
2248+
preload: dotnetPreloads("interp"),
2249+
iterations: 10,
2250+
worstCaseCount: 2,
2251+
tags: ["Wasm", "dotnet"]
2252+
}),
2253+
new AsyncBenchmark({
2254+
name: "dotnet-aot",
2255+
files: [
2256+
"./wasm/dotnet/aot.js",
2257+
"./wasm/dotnet/benchmark.js",
2258+
],
2259+
preload: dotnetPreloads("aot"),
2260+
iterations: 15,
2261+
worstCaseCount: 2,
2262+
tags: ["Wasm", "dotnet"]
2263+
})
22152264
];
22162265

22172266
// LuaJSFight tests

in-depth.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,20 @@ <h3>
776776
Source code: <a href="proxy/vue-benchmark.js">vue-benchmark.js</a>
777777
</dd>
778778

779+
<dt id="dotnet-interp">dotnet-interp</dt>
780+
<dd>
781+
Tests <a href="https://github.com/dotnet/runtime">.NET on WebAssembly</a>. This benchmark tests operations
782+
on .NET implementation of String, JSON serialization, specifics of .NET exceptions and computation
783+
of a 3D scene using Mono Interpreter. Source code: <a href="wasm/dotnet">.NET</a>.
784+
</dd>
785+
786+
<dt id="dotnet-aot">dotnet-aot</dt>
787+
<dd>
788+
Tests <a href="https://github.com/dotnet/runtime">.NET on WebAssembly</a>. This benchmark tests operations
789+
on .NET implementation of String, JSON serialization, specifics of .NET exceptions and computation
790+
of a 3D scene using Mono AOT. Source code: <a href="wasm/dotnet">.NET</a>.
791+
</dd>
792+
779793
</dl>
780794

781795
<p><a href="index.html" class="button">&larr; Return to Tests</a></p>

wasm/dotnet/.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
*.binlog
2+
.dotnet
3+
.nuget
4+
bin
5+
obj
6+
blazor.boot.json
7+
web.config
8+
*.staticwebassets.endpoints.json

wasm/dotnet/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# .NET on WebAssembly
2+
3+
Tests [.NET on WebAssembly](https://github.com/dotnet/runtime). This benchmark tests operations
4+
on .NET implementation of String, JSON serialization, specifics of .NET exceptions and computation
5+
of a 3D scene using Mono Interpreter & AOT. Source code: [.NET](wasm/dotnet)
6+
7+
## Build instructions
8+
9+
Download .NET SDK 9.0.3xx
10+
11+
- [dotnet-sdk-win-x64.zip](https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-win-x64.zip)
12+
- [dotnet-sdk-linux-x64.tar.gz](https://aka.ms/dotnet/9.0.3xx/daily/dotnet-sdk-linux-x64.tar.gz)
13+
14+
Run `build.sh` script. It will install `wasm-tools` workload & build the benchmark code twice (for Mono interpreter & AOT).
15+
16+
To run the benchmark code on `jsc`, we are prepending `import.meta.url ??= ""` to `dotnet.js`.
17+
18+
## Background on .NET / build output files
19+
20+
Mono AOT works in a "mixed mode". It is not able to compile all code patterns and in various scenarios it falls back to interpreter.
21+
Because of that we are still loading managed dlls (all the other not-`dotnet.native.wasm` files).
22+
23+
Structure of the build output
24+
25+
- `dotnet.js` is entrypoint JavaScript with public API.
26+
- `dotnet.runtime.js` is internal implementation of JavaScript logic for .NET.
27+
- `dotnet.native.js` is emscripten module configured for .NET.
28+
- `dotnet.native.wasm` is unmanaged code (Mono runtime + AOT compiled code).
29+
- `System.*.wasm` is .NET BCL that has unused code trimmed away.
30+
- `dotnet.wasm` is the benchmark code.

wasm/dotnet/aot.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
globalThis.dotnetFlavor = "aot";

wasm/dotnet/benchmark.js

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
class Benchmark {
2+
async init() {
3+
const config = {
4+
mainAssemblyName: "dotnet.dll",
5+
globalizationMode: "custom",
6+
assets: [
7+
{
8+
name: "dotnet.runtime.js",
9+
resolvedUrl: dotnetRuntimeUrl,
10+
moduleExports: await dynamicImport(dotnetRuntimeUrl),
11+
behavior: "js-module-runtime"
12+
},
13+
{
14+
name: "dotnet.native.js",
15+
resolvedUrl: dotnetNativeUrl,
16+
moduleExports: await dynamicImport(dotnetNativeUrl),
17+
behavior: "js-module-native"
18+
},
19+
{
20+
name: "dotnet.native.wasm",
21+
resolvedUrl: wasmBinaryUrl,
22+
buffer: await getBinary(wasmBinaryUrl),
23+
behavior: "dotnetwasm"
24+
},
25+
{
26+
name: "icudt_CJK.dat",
27+
resolvedUrl: icuCustomUrl,
28+
buffer: await getBinary(icuCustomUrl),
29+
behavior: "icu"
30+
},
31+
{
32+
name: "System.Collections.Concurrent.wasm",
33+
resolvedUrl: dllCollectionsConcurrentUrl,
34+
buffer: await getBinary(dllCollectionsConcurrentUrl),
35+
behavior: "assembly"
36+
},
37+
{
38+
name: "System.Collections.wasm",
39+
resolvedUrl: dllCollectionsUrl,
40+
buffer: await getBinary(dllCollectionsUrl),
41+
behavior: "assembly"
42+
},
43+
{
44+
name: "System.ComponentModel.Primitives.wasm",
45+
resolvedUrl: dllComponentModelPrimitivesUrl,
46+
buffer: await getBinary(dllComponentModelPrimitivesUrl),
47+
behavior: "assembly"
48+
},
49+
{
50+
name: "System.ComponentModel.TypeConverter.wasm",
51+
resolvedUrl: dllComponentModelTypeConverterUrl,
52+
buffer: await getBinary(dllComponentModelTypeConverterUrl),
53+
behavior: "assembly"
54+
},
55+
{
56+
name: "System.Drawing.Primitives.wasm",
57+
resolvedUrl: dllDrawingPrimitivesUrl,
58+
buffer: await getBinary(dllDrawingPrimitivesUrl),
59+
behavior: "assembly"
60+
},
61+
{
62+
name: "System.Drawing.wasm",
63+
resolvedUrl: dllDrawingUrl,
64+
buffer: await getBinary(dllDrawingUrl),
65+
behavior: "assembly"
66+
},
67+
{
68+
name: "System.IO.Pipelines.wasm",
69+
resolvedUrl: dllIOPipelinesUrl,
70+
buffer: await getBinary(dllIOPipelinesUrl),
71+
behavior: "assembly"
72+
},
73+
{
74+
name: "System.Linq.wasm",
75+
resolvedUrl: dllLinqUrl,
76+
buffer: await getBinary(dllLinqUrl),
77+
behavior: "assembly"
78+
},
79+
{
80+
name: "System.Memory.wasm",
81+
resolvedUrl: dllMemoryUrl,
82+
buffer: await getBinary(dllMemoryUrl),
83+
behavior: "assembly"
84+
},
85+
{
86+
name: "System.ObjectModel.wasm",
87+
resolvedUrl: dllObjectModelUrl,
88+
buffer: await getBinary(dllObjectModelUrl),
89+
behavior: "assembly"
90+
},
91+
{
92+
name: "System.Private.CoreLib.wasm",
93+
resolvedUrl: dllPrivateCorelibUrl,
94+
buffer: await getBinary(dllPrivateCorelibUrl),
95+
behavior: "assembly",
96+
isCore: true
97+
},
98+
{
99+
name: "System.Runtime.InteropServices.JavaScript.wasm",
100+
resolvedUrl: dllRuntimeInteropServicesJavaScriptUrl,
101+
buffer: await getBinary(dllRuntimeInteropServicesJavaScriptUrl),
102+
behavior: "assembly",
103+
isCore: true
104+
},
105+
{
106+
name: "System.Text.Encodings.Web.wasm",
107+
resolvedUrl: dllTextEncodingsWebUrl,
108+
buffer: await getBinary(dllTextEncodingsWebUrl),
109+
behavior: "assembly"
110+
},
111+
{
112+
name: "System.Text.Json.wasm",
113+
resolvedUrl: dllTextJsonUrl,
114+
buffer: await getBinary(dllTextJsonUrl),
115+
behavior: "assembly"
116+
},
117+
{
118+
name: "dotnet.wasm",
119+
resolvedUrl: dllAppUrl,
120+
buffer: await getBinary(dllAppUrl),
121+
behavior: "assembly",
122+
isCore: true
123+
}
124+
]
125+
};
126+
127+
this.dotnet = (await dynamicImport(dotnetUrl)).dotnet;
128+
this.api = await this.dotnet.withModuleConfig({ locateFile: e => e }).withConfig(config).create();
129+
this.exports = await this.api.getAssemblyExports("dotnet.dll");
130+
131+
this.hardwareConcurrency = 1;
132+
this.sceneWidth = dotnetFlavor === "aot" ? 300 : 150;
133+
this.sceneHeight = dotnetFlavor === "aot" ? 200 : 100;
134+
}
135+
async runIteration() {
136+
await this.exports.Interop.RunIteration(this.sceneWidth, this.sceneHeight, this.hardwareConcurrency);
137+
}
138+
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)