Skip to content

Conversation

kmiller68
Copy link
Contributor

Add a pass to the build script that replaces them with the non-legacy execptions. This doesn't seem to impact performance. The dotnet runtime still seems to generate one module/function that has a legacy exception but that function is never called. It's also somewhat degenerate since it's just (try catch_all) and has no other body.

This doesn't seem to make a difference for the score in all CLIs and we don't want legacy exception usage in JetStream to be the thing that keeps the legacy wasm exceptions "feature" alive.

Note: I didn't run the build script. I just ran the wasm-opt commands on the build products. Mostly because when I recompile the code doesn't run or is 5x slower than the previous binaries.

@kmiller68 kmiller68 requested a review from danleh September 19, 2025 18:00
Copy link

netlify bot commented Sep 19, 2025

Deploy Preview for webkit-jetstream-preview ready!

Name Link
🔨 Latest commit 3de5730
🔍 Latest deploy log https://app.netlify.com/projects/webkit-jetstream-preview/deploys/68cda1a4f4a3450007e85875
😎 Deploy Preview https://deploy-preview-188--webkit-jetstream-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Add a pass to the build script that replaces them with the non-legacy
execptions. This doesn't seem to impact performance. The dotnet runtime
still seems to generate one module/function that has a legacy exception
but that function is never called. It's also somewhat degenerate
since it's just `(try catch_all)` and has no other body.

This doesn't seem to make a difference for the score in all CLIs and we
don't want legacy exception usage in JetStream to be the thing that
keeps the legacy wasm exceptions "feature" alive.

Note: I didn't run the build script. I just ran the wasm-opt
commands on the build products. Mostly because when I recompile
the code doesn't run or is 5x slower than the previous binaries.
@kmiller68 kmiller68 force-pushed the dotnet-legacy-exceptions branch from fe8bc49 to 3de5730 Compare September 19, 2025 18:32
echo "Copying symbol maps..." | tee -a "$BUILD_LOG"
cp ./src/dotnet/obj/Release/net9.0/wasm/for-publish/dotnet.native.js.symbols ./build-interp/wwwroot/_framework/

for wasmFile in $(find "./build-interp" -type f -name "*.wasm");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a comment explaining this step.

@danleh
Copy link
Contributor

danleh commented Sep 19, 2025

Generally SGTM to avoid depending on legacy EH, but:

  1. Let's get some insight from MSFT: @maraf Can we configure dotnet/Blazor to use exnref by default? Do you have any plans to change the default? Ideally, I would like to avoid the additional binaryen step (to simplify things and keep them more similar to the real-world build).
  2. @kmiller68 Why does it no longer run when you rebuild? Sounds like we should fix the build script for good then.
  3. What's the effect of binaryen/wasm-opt besides moving to exnref? Does it otherwise affect the binaries? (E.g., in terms of code size).

@pavelsavara
Copy link

generate one module/function that has a legacy exception but that function is never called. It's also somewhat degenerate since it's just (try catch_all) and has no other body.

What's the name of the function ? Or how do I find it ?

@kmiller68
Copy link
Contributor Author

Let's get some insight from MSFT: @maraf Can we configure dotnet/Blazor to use exnref by default? Do you have any plans to change the default? Ideally, I would like to avoid the additional binaryen step (to simplify things and keep them more similar to the real-world build)

Agreed, would be good to know this. I would also highly encourage switching to exnref ASAP since the legacy exceptions is deprecated.

@kmiller68 Why does it no longer run when you rebuild? Sounds like we should fix the build script for good then.

I think it might have been a stale build artifact from a prior build. If I remove the additions to rm I can reproduce pretty easily. I'm following up with @maraf "offline" but the rm -r src/dotnet/bin src/dotnet/obj seems to fix the issue. Although it does still have the performance cliff sometimes.

What's the effect of binaryen/wasm-opt besides moving to exnref? Does it otherwise affect the binaries? (E.g., in terms of code size).

It looks like they're roughly the same size. For dotnet.native.wasm it changed:

(bytes) legacy exnref growth
interp 2793827 2794485 .02%
aot 7992234 7997676 .07%

@kmiller68
Copy link
Contributor Author

What's the name of the function ? Or how do I find it ?

It doesn't appear to have a name anywhere. The entire module is just

(module
  (type $t0 (func))
  (func $f0 (type $t0)
    (try $T0
      (do)
      (catch_all))))

which makes me think it's some kind of dynamically generated module in the interp variant of the benchmark.

@pavelsavara
Copy link

I think we are using legacy feature detection but should be using new one

@kmiller68
Copy link
Contributor Author

Oh interesting, I think the benchmark still executes legacy exceptions, at least enough to trigger a tier up to our optimizing tiers for aot. I added some logging but I don't know which module they're coming from.

Running dotnet-aot-wasm:
Try added in function mid-tier optimized code index: 21404 named:
Try added in function mid-tier optimized code index: 819 named:
Try added in function mid-tier optimized code index: 15686 named:
Try added in function fully optimized code index: 21404 named:
Try added in function fully optimized code index: 21404 named:
Try added in function fully optimized code index: 21404 named:
Try added in function fully optimized code index: 21404 named:
Try added in function fully optimized code index: 21404 named:
Try added in function mid-tier optimized code index: 22 named:
Try added in function mid-tier optimized code index: 15 named:
Try added in function mid-tier optimized code index: 15 named:
Try added in function mid-tier optimized code index: 15 named:
Try added in function mid-tier optimized code index: 15 named:
Try added in function mid-tier optimized code index: 15 named:
Try added in function mid-tier optimized code index: 15 named:
Try added in function mid-tier optimized code index: 15 named:
Try added in function fully optimized code index: 15 named:
Try added in function fully optimized code index: 15 named:
Try added in function fully optimized code index: 15 named:
Try added in function fully optimized code index: 15 named:
Try added in function fully optimized code index: 15 named:
Try added in function fully optimized code index: 15 named:
Try added in function fully optimized code index: 15 named:
Try added in function fully optimized code index: 15 named:
Try added in function fully optimized code index: 15 named:
Try added in function fully optimized code index: 15 named:
Try added in function fully optimized code index: 15 named:
Try added in function fully optimized code index: 15 named:
Try added in function fully optimized code index: 15 named:
Try added in function fully optimized code index: 15 named:
Try added in function mid-tier optimized code index: 3158 named:
Try added in function mid-tier optimized code index: 3158 named:
Try added in function mid-tier optimized code index: 3158 named:
Try added in function mid-tier optimized code index: 1574 named:
Try added in function mid-tier optimized code index: 1575 named:
Try added in function mid-tier optimized code index: 19 named:
Try added in function mid-tier optimized code index: 19 named:
Try added in function mid-tier optimized code index: 91 named:
Try added in function mid-tier optimized code index: 75 named:
Try added in function mid-tier optimized code index: 75 named:
Try added in function mid-tier optimized code index: 7842 named:
Try added in function mid-tier optimized code index: 15688 named:
Try added in function mid-tier optimized code index: 26256 named:
Try added in function mid-tier optimized code index: 27 named:
Try added in function mid-tier optimized code index: 27 named:
Try added in function mid-tier optimized code index: 7712 named:
Try added in function mid-tier optimized code index: 7505 named:
Try added in function mid-tier optimized code index: 7516 named:
Try added in function mid-tier optimized code index: 7433 named:
Try added in function mid-tier optimized code index: 15687 named:
    First: 8.69
    Worst: 47.83
    Average: 58.59
    Score: 28.98
    Wall-Time: 1944.920 ms

@pavelsavara
Copy link

Looking deeper into the issue. Net9 and Net10 both use Emscripten version 3.1.56, which doesn't support final EH spec. Our JetStream benchmark is compiled with Net9.

I think that we would need to upgrade Emscripten to at least 4.0.0 in order to use -s WASM_LEGACY_EXCEPTIONS=0.
Tooling upgrade could possibly happen in Net11.

I created dotnet/runtime#119961 for that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants