В .NET 6 запланирована поддержка AOT компиляции для Blazor WebAssembly приложений. Давайте попробуем запустить в Preview 2 версии.

Анонса и инструкций пока что нету. Поэтому и решено написать этот пост.

Краткая справка

Немного восстановим в памяти.

Blazor - Single Page Application веб-фреймворк от Майкрософт. Отличительная особенность: за динамику отвечает C#, а не привычный нам JavaScript.

Существует две версии:

Blazor Server. Код запускается на сервере, страница рендерится на сервере. Через веб-сокеты передаем измененную часть страницы и с помощью JS обновляем html в браузере. Здесь нам AOT не интересен.

Blazor WebAssembly. В браузере на WebAssembly запускается порезанная версия Mono. А уже на Mono запускается наше .NET приложение. Рендеринг страницы и вся логика в браузере. Сервер нужен только чтобы отдать скомпилированную статику.

Пытливый читатель сразу предположит, что наверняка мы теряем в скорости из-за дополнительной прослойки WebAssembly-Mono-Наше приложение. И будет прав! Именно для этого нам и нужна Ahead-of-Time компиляция, которая позволяет из .NET приложения сразу скомпилировать версию для WebAssembly.

Инструкция по запуску

Здесь нам важно использовать именно указанные версии. Потому что шаг влево, шаг вправо - не работает. И не всегда получается разобраться почему. Если вы читаете этот пост сильно позже марта 2021, то вероятно стоит поэкспериментировать с более свежими версиями.

Я все делал на Windows. В теории на других ОС тоже должно работать.

Устанавливаем SDK 6.0.100-preview.2. Просто скачать и запустить установщик.

Устанавливаем Emscripten. Это как раз и есть компилятор в WebAssembly.

Шаги для установки:

git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
emsdk install 2.0.12
emsdk activate 2.0.12
emsdk_env.bat

Теперь консоль можно закрыть и в Environment Variables надо добавить EMSDK_PATH с путем до папки emsdk.

Инструкция для установки на других ОС. Версию 2.0.12 используем по совету.

Ставим пакет dotnet-install-blazoraot. Этот пакет как раз подружит dotnet и emscripten.

dotnet tool install -g dotnet-install-blazoraot --version 6.0.0-*
dotnet install-blazoraot

В одном из пакетов есть баг, он уже пофикшен в репозитории, но еще не выпущен. Так что пока что придется подправить локально.

В файле C:\Program Files\dotnet\packs\Microsoft.NET.Runtime.WebAssembly.Sdk\6.0.0-preview.2.21154.6\Sdk\WasmApp.targets меняем строчку 244 на:

<Exec Condition="'$(WasmLinkIcalls)' == 'true'" Command="&quot;$(MonoAotCrossCompilerPath)&quot; --print-icall-table > $(_WasmIntermediateOutputPath)/runtime-icall-table.h" />

С подготовкой мы закончили. Можем создать первое приложение:

mkdir myapp
cd myapp
dotnet new blazorwasm

И нам надо сконфигурировать RunAOTCompilation в csproj:

<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference
          Include="Microsoft.AspNetCore.Components.WebAssembly"
          Version="6.0.0-preview.2.21154.6" />
    <PackageReference
          Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer"
          Version="6.0.0-preview.2.21154.6" PrivateAssets="all" />
  </ItemGroup>

  <PropertyGroup>
    <RunAOTCompilation>true</RunAOTCompilation>
  </PropertyGroup>
</Project>

AOT компиляция будет работать только во время публикации. Поэтому публикуем приложение:

dotnet publish

Первые впечатления

Компиляция занимает значительное время. Нечто простое всего несколько минут. А вот один далеко не самый большой проект у меня компилируется полчаса.

Скомпилированный dotnet.wasm файл даже для дефолтного приложения 15 мб. Я легко получал и 50 и 60 мб. Это ожидаемо.

Элементарные события, например, клики на кнопки срабатывают, но в консоль сыпят ошибками. Асинхронные обработчики не работают. Пока что не получилось разобраться почему. Присоединяйтесь :)

НО! Скорость действительно заметно быстрее.

Я сделал эксперимент с одной из вычислительных задач: поиск простого числа. С AOT выходит в 3 раза меньше времени!

Для желающих самостоятельно проверить есть два одинаковых приложения.

> Версия с AOT

> Версия без AOT

Заключение

Чуда не случилось. Придется оптимизировать имеющийся код :)

Вся эта история еще в самом начале пути. В ближайшие полгода, думаю, не стоит рассчитывать на легкий способ увеличить производительность своих приложений.

Но эксперимент очень интересный. Посмотрим, куда приведет и что получится.