Skip to content

Better support for building SIMD and no-SIMD WebAssembly in the same project #78872

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
FranklinWhale opened this issue Nov 26, 2022 · 7 comments
Assignees
Labels
arch-wasm WebAssembly architecture area-Build-mono
Milestone

Comments

@FranklinWhale
Copy link

SIMD improves the performance of WebAssembly, but Safari and the Enhanced Security Mode of Microsoft Edge do not support it. As a result, we build 2 Wasm versions (one with SIMD and one without) in our project and utilize WebAssembly Feature Detection to load appropriate version at runtime:

const { dotnet } = await import(`./${await simd() ? "simd" : "no-simd"}/dotnet.js`);

With the following configurations in the csproj file,

<PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <Nullable>enable</Nullable>
    <RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
    <WasmMainJSPath>main.js</WasmMainJSPath>
    <OutputType>Exe</OutputType>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    <WasmEnableThreads>true</WasmEnableThreads>
    <RunAOTCompilation>true</RunAOTCompilation>
    <WasmEnableExceptionHandling>true</WasmEnableExceptionHandling>
    <EnableMLUnsupportedPlatformTargetCheck>false</EnableMLUnsupportedPlatformTargetCheck>
    <InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
<Choose>
    <When Condition="'$(Configuration)' != 'NoSIMD'">
        <PropertyGroup>
            <WasmEnableSIMD>true</WasmEnableSIMD>
        </PropertyGroup>
    </When>
</Choose>

The build script runs dotnet publish twice:

dotnet publish -c Release
dotnet publish -c NoSIMD --no-restore

As the project is effectively built twice, the build process takes quite some time. I hope something can be done to improve the build performance.

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Nov 26, 2022
@ghost
Copy link

ghost commented Nov 26, 2022

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@radical radical added arch-wasm WebAssembly architecture area-Build-mono labels Nov 27, 2022
@ghost
Copy link

ghost commented Nov 27, 2022

Tagging subscribers to 'arch-wasm': @lewing
See info in area-owners.md if you want to be subscribed.

Issue Details

SIMD improves the performance of WebAssembly, but Safari and the Enhanced Security Mode of Microsoft Edge do not support it. As a result, we build 2 Wasm versions (one with SIMD and one without) in our project and utilize WebAssembly Feature Detection to load appropriate version at runtime:

const { dotnet } = await import(`./${await simd() ? "simd" : "no-simd"}/dotnet.js`);

With the following configurations in the csproj file,

<PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <Nullable>enable</Nullable>
    <RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
    <WasmMainJSPath>main.js</WasmMainJSPath>
    <OutputType>Exe</OutputType>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    <WasmEnableThreads>true</WasmEnableThreads>
    <RunAOTCompilation>true</RunAOTCompilation>
    <WasmEnableExceptionHandling>true</WasmEnableExceptionHandling>
    <EnableMLUnsupportedPlatformTargetCheck>false</EnableMLUnsupportedPlatformTargetCheck>
    <InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
<Choose>
    <When Condition="'$(Configuration)' != 'NoSIMD'">
        <PropertyGroup>
            <WasmEnableSIMD>true</WasmEnableSIMD>
        </PropertyGroup>
    </When>
</Choose>

The build script runs dotnet publish twice:

dotnet publish -c Release
dotnet publish -c NoSIMD --no-restore

As the project is effectively built twice, the build process takes quite some time. I hope something can be done to improve the build performance.

Author: FranklinWhale
Assignees: -
Labels:

arch-wasm, untriaged, area-Build-mono

Milestone: -

@radical radical added this to the 8.0.0 milestone Nov 27, 2022
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Nov 27, 2022
@radical
Copy link
Member

radical commented Nov 27, 2022

The native part of the build - AOT, compile-with-emcc, and linking - are probably the ones taking the most time. Enabling SIMD causes different arguments to be passed for the various steps, thus potentially different intermediate outputs. IOW, it is not really shareable.

Having said that, it might be interesting to think of how somebody might go about producing multiple builds with different wasm feature settings. I can think of some ways that might be somewhat convoluted (eg. sharing some differentiated intermediate output files), but I can't say if any of that would be worth the effort.
cc @radekdoulik @kg @vargaz @lewing

@kg
Copy link
Member

kg commented Nov 27, 2022

I'm not really sure which outputs or intermediate files could be shared, really. Your managed assemblies potentially could, but since you're building with a different configuration the inputs to roslyn will be different so we can't assume that any of it can be reused. Once things like the linker or AOT kick in it's all going to be different, as @radical says.

How large is the project you're building and how long does it take? If you're experiencing unusually long build times that may be worth looking into, and optimizing those build times will have 2x the benefit for you :)

@FranklinWhale
Copy link
Author

The project is not complex, as it only has the following references, but it takes 20 minutes to complete 2 builds. That said, I don't think the build time is unusually long.

<ItemGroup>
    <PackageReference Include="Microsoft.Data.Analysis" Version="0.20.*" />
    <PackageReference Include="Microsoft.ML" Version="2.0.*" />
    <PackageReference Include="Microsoft.ML.FastTree" Version="2.0.*" />
    <PackageReference Include="Microsoft.ML.OnnxConverter" Version="0.20.*" />
    <PackageReference Include="Microsoft.NET.WebAssembly.Threading" Version="7.0.*" />
</ItemGroup>

One thing that significantly speeds up the building process is to preserved the previously built items (i.e. not to delete bin and obj folders), as AOT applies to modified assemblies only.

As we come to the conclusion that no intermediate files can be shared, perhaps this issue may be closed :)

@kg
Copy link
Member

kg commented Nov 28, 2022

20 minutes does seem unusually long unless the project contains a lot of C# source code or those dependencies are extremely complex. It might be worth filing a separate issue about it, if only so we can track that and other users can chime in if they have similar build time problems.

@radekdoulik radekdoulik modified the milestones: 8.0.0, 9.0.0 Jul 26, 2023
@radekdoulik
Copy link
Member

Moving to NET9.

Some preliminary work is already done #89387 - feature detection for SIMD and EH

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
arch-wasm WebAssembly architecture area-Build-mono
Projects
None yet
Development

No branches or pull requests

6 participants