European ASP.NET 4.5 Hosting BLOG

BLOG about ASP.NET 4, ASP.NET 4.5 Hosting and Its Technology - Dedicated to European Windows Hosting Customer

European Blazor Hosting - HostForLIFE :: Ahead-Of-Time Compilation For Blazor WASM

clock January 25, 2023 07:20 by author Peter

Ahead-of-Time (AOT) compilation is a technique used in Blazor WebAssembly (WASM) to precompile C# code into machine code before it is executed by the browser. This technique is used to improve the startup time and performance of Blazor WASM applications.


The AOT compiler can be used to compile the entire application or just specific parts of it, such as frequently called methods. This can help to reduce the size of the deployed application and improve startup time. Additionally, the AOT compiler can also perform other optimizations, such as inlining and dead code elimination, to further improve performance.

AOT with Blazor WASM
When a Blazor WASM application is run in the browser, the C# code is first compiled to WebAssembly (WASM) bytecode using the Mono runtime. This bytecode is then interpreted by the browser's WebAssembly engine to execute the application. However, this interpretation process can be slow and result in poor performance. AOT compilation solves this problem by precompiling the C# code into machine code that can be executed directly by the browser's WebAssembly engine, without the need for interpretation.

AOT compilation is performed using the Mono runtime's Ahead-of-Time (AOT) compiler, which is a command-line tool that takes the C# code and generates machine code for the specific platform and architecture that the application will be running on. The generated machine code is then included as a binary file in the application's deployment package, which is loaded by the browser when the application is run.

Ahead-of-Time (AOT) compilation is a technique that is used to improve the performance of Blazor WebAssembly (WASM) applications by precompiling the C# code into machine code before it is executed by the browser. This technique is particularly useful in Blazor WASM because it allows the C# code to be executed directly by the browser's WebAssembly engine, rather than being interpreted by the Mono runtime. This can result in significant performance improvements, particularly for applications that have a lot of C# code or that are deployed over the internet.

The process of AOT compilation starts with the C# code that makes up the Blazor WASM application. This code is then passed through the Mono runtime's Ahead-of-Time (AOT) compiler, which generates machine code for the specific platform and architecture that the application will be running on. The generated machine code is then included as a binary file in the application's deployment package, which is loaded by the browser when the application is run.

One of the key advantages of AOT compilation is that it improves the startup time of Blazor WASM applications. This is because the compiled machine code can be executed directly by the browser's WebAssembly engine, without the need for interpretation. This can result in significant performance improvements, particularly for applications that have a lot of C# code or that are deployed over the internet.

Another advantage of AOT compilation is that it can help to reduce the size of the deployed application. This is because the AOT compiler can perform other optimizations, such as inlining and dead code elimination, which can reduce the size of the generated machine code. This can be beneficial for applications that are deployed over the internet, as it can reduce the amount of data that needs to be downloaded by the browser.

The AOT compiler can also be used to compile specific parts of the application, such as frequently called methods. This can help to further improve the performance of the application by reducing the amount of C# code that needs to be interpreted by the Mono runtime. Additionally, the AOT compiler can also perform other optimizations, such as inlining and dead code elimination, to further improve performance.

In addition to improving the performance of Blazor WASM applications, AOT compilation can also help to improve the security of the application. This is because the AOT compiler can perform additional security checks on the C# code, such as checking for buffer overflows and other types of security vulnerabilities. Additionally, the AOT compiler can also perform other optimizations, such as inlining and dead code elimination, to further improve security.

In summary, AOT compilation is a powerful technique that is used to improve the performance of Blazor WebAssembly (WASM) applications by precompiling the C# code into machine code before it is executed by the browser. This technique can result in significant performance improvements, particularly for applications that have a lot of C# code or that are deployed over the internet. Additionally, AOT compilation can also help to reduce the size of the deployed application and improve the security of the application.

How to integrate AOT in Blazor WASM
To add Ahead-of-Time (AOT) compilation to a Blazor WebAssembly (WASM) project, you will need to use the Mono runtime's Ahead-of-Time (AOT) compiler, which is a command-line tool that takes the C# code and generates machine code for the specific platform and architecture that the application will be running on.

Here is an example of how to use the AOT compiler to compile a Blazor WASM project:

Step 1. Make sure you have the latest version of the .NET Core SDK and the Mono runtime installed on your machine.
Step 2. Open the command prompt and navigate to the root directory of your Blazor WebAssembly project.
Step 3. Run the following command to install the AOT compiler package:

dotnet add package Mono.WebAssembly.Interop


Step 4. Open the Program.cs file of your project.
Step 5. In the Main method, after calling builder.Build().Run(), and add the following line:
builder.UseBlazorWebAssemblyAot();

Step 6. Run the following command to build your project with AOT compilation:
dotnet publish -r browser-wasm --self-contained true

Step 7. This will build your project with AOT compilation and place the output files in the "bin/Release/netstandard2.1/browser-wasm" folder.

Merits of using AOT

  • AOT (ahead-of-time) compilation in Blazor WebAssembly (WASM) provides several benefits, including improved performance, reduced download size, and increased security.
  • Improved Performance: AOT compilation results in faster startup times and improved runtime performance, as the code is already compiled and ready to be executed.
  • Reduced Download Size: AOT compilation reduces the size of the code that needs to be downloaded to the client, as the C# code is transformed into optimized machine code that is specific to the client's platform.
  • Increased Security: AOT compilation makes it more difficult for attackers to reverse-engineer or tamper with the application's code, as the C# code is transformed into machine code that is not easily readable or editable.
  • Reduced Startup Time: AOT compilation eliminates the need for the browser to perform Just-In-Time (JIT) compilation, reducing the time it takes for the application to start up.
  • Enhanced Debugging: AOT compilation makes it easier to debug the application, as the C# code is transformed into machine code that can be more easily correlated with the original code.
  • Better Memory Management: AOT compilation reduces the number of runtime checks and improves memory management.
  • Overall, AOT compilation can improve the overall user experience and increase the security of your Blazor WASM application.

Demerits

  • While AOT compilation in Blazor WebAssembly (WASM) has many benefits, it also has some drawbacks:
  • Increased Build Time: AOT compilation requires additional build time, as the C# code needs to be transformed into machine code for each platform and architecture. This can increase the time it takes to build and deploy the application.
  • Limited Flexibility: AOT compilation results in a more rigid application, as the code cannot be easily modified at runtime. This can make it more difficult to add new features or fix bugs.
  • Limited Platform Support: AOT compilation requires that the application be compiled for each specific platform and architecture. This can limit the number of platforms that the application can run on.
  • Limited Debugging: AOT compilation makes it more difficult to debug the application, as the machine code may not be easily correlated with the original C# code.
  • Reduced ability to optimize: AOT compilation doesn't give the opportunity to use JIT (Just in Time) compilation for optimizing the performance during runtime.
  • Harder to update: Since the application is precompiled, updating the application can be more complex and time-consuming.
  • It's important to consider the specific needs of your application before deciding whether or not to use AOT compilation. In some cases, the benefits may outweigh the drawbacks, while in other cases, the drawbacks may make AOT compilation less desirable.

In conclusion, AOT compilation in Blazor WebAssembly (WASM) provides several benefits, including improved performance, reduced download size, and increased security. However, it also has some drawbacks such as increased build time, limited flexibility, limited platform support, limited debugging, and harder to update. It's important to consider the specific needs of your application before deciding whether or not to use AOT compilation. If the application requires fast startup times, improved runtime performance, and increased security, AOT compilation may be a good choice. However, if the application requires the ability to easily modify the code at runtime, or the ability to run on a wide range of platforms, AOT compilation may not be the best choice.



European Blazor Hosting - HostForLIFE :: Blazor WASM - Cache Storage Using JavaScript

clock December 9, 2022 06:08 by author Peter

Browser Storage
Storing something in the browser to access it easier & frequently with less load time.

Types of browser storage

There are 6 types of browser storage:

  • Cache
  • Cookie
  • Indexed DB
  • Local storage
  • Memory
  • Session storage

Compare browser storage types

  Its Lifetime Allowed data type Shared between browser tabs
Cache Until deleted Request, Response YES
Cookie Expired time / until deleted Key value YES
Indexed DB Until deleted Various types YES
Local storage Until deleted Key value YES
Memory Users exist/ close browser tab Various types NO
Session storage Users exist/ close browser tab Key value NO

In this article, we are going to see about cache storage and how to implement this in Blazor WASM using JavaScript.

Cache Storage
Store any request/responses as cache in browser to speed up the loading process.

Benefits

  • Improves performance
  • Reduce call to servers
  • Provide offline data support

Step 2
Create razor page named CacheStorage.razor and add following code to activate cache storage and its operations
@page "/cache"
@inject MyBlazorWasmApp.Helper.CacheStorageAccessor CacheStorageAccessor
@inject HttpClient HttpClient
<h3>CacheStorage</h3>
<hr />
<button class="btn btn-primary" type="button" @onclick="SetValueAsync">Set Value</button>
<div>Stored Value: @StoredValue</div>
<button class="btn btn-primary" type="button" @onclick="GetValueAsync">Get Value</button>
<button class="btn btn-primary" type="button" @onclick="RemoveAsync">Remove Value</button>
<button class="btn btn-primary" type="button" @onclick="ClearAllAsync">Clear All</button>
@code {
    public string StoredValue { get; set; } = "";
    public async Task SetValueAsync()
    {
        var message = CreateMessage();
        var response = await HttpClient.SendAsync(message);
        await CacheStorageAccessor.StoreAsync(message, response);
    }
    public async Task GetValueAsync()
    {
        StoredValue = await CacheStorageAccessor.GetAsync(CreateMessage());
    }
    public async Task RemoveAsync()
    {
        await CacheStorageAccessor.RemoveAsync(CreateMessage());
    }
    public async Task ClearAllAsync()
    {
        await CacheStorageAccessor.RemoveAllAsync();
    }
    public HttpRequestMessage CreateMessage() => new HttpRequestMessage(HttpMethod.Get, "/sample-data/weather.json");
}

The razor page will call respective JavaScript function to process cache

Step 3
Setup JavaScript file with below code
async function openCacheStorage() {
    return await window.caches.open("Kajul - Blazor App");
}

function createRequest(url, method, body = "") {
    let requestInit = {
        method: method
    };
    if (body != "") {
        requestInit.body = body;
    }
    let request = new Request(url, requestInit);
    console.log(request);
    return request;
}
//In your JavaScript module, add functions to store, get, delete the data:
export async function store(url, method, body = "", responseString) {
    let kajulBlazorCache = await openCacheStorage();
    let request = createRequest(url, method, body);
    let response = new Response(responseString);
    await kajulBlazorCache.put(request, response);
}
export async function get(url, method, body = "") {
    let kajulBlazorCache = await openCacheStorage();
    let request = createRequest(url, method, body);
    let response = await kajulBlazorCache.match(request);
    if (response == undefined) {
        return "";
    }
    let result = await response.text();
    return result;
}
export async function remove(url, method, body = "") {
    let kajulBlazorCache = await openCacheStorage();
    let request = createRequest(url, method, body);
    await kajulBlazorCache.delete(request);
}
export async function removeAll() {
    let kajulBlazorCache = await openCacheStorage();
    let requests = await kajulBlazorCache.keys();
    for (let i = 0; i < requests.length; i++) {
        await kajulBlazorCache.delete(requests[i]);
    }
}

Step 4
Create a helper class (CacheStorageAccessor.cs) to connect razor and JavaScript functions
using Microsoft.JSInterop;
namespace MyBlazorWasmApp.Helper;
public class CacheStorageAccessor: IAsyncDisposable {
    private Lazy < IJSObjectReference > _accessorJsRef = new();
    private readonly IJSRuntime _jsRuntime;
    //constructor
    public CacheStorageAccessor(IJSRuntime jsRuntime) {
        _jsRuntime = jsRuntime;
    }
    //Common method - You will need to call WaitForReference() in all methods.
    private async Task WaitForReference() {
        if (_accessorJsRef.IsValueCreated is false) {
            _accessorJsRef = new(await _jsRuntime.InvokeAsync < IJSObjectReference > ("import", "/js/CacheStorageAccessor.js"));
        }
    }
    //Always remember to dispose the JavaScript module.
    public async ValueTask DisposeAsync() {
        if (_accessorJsRef.IsValueCreated) {
            await _accessorJsRef.Value.DisposeAsync();
        }
    }
    #region create a new method
    for each operation
    //the below is C# blazor methods will link the js functions respective to its name
    public async Task StoreAsync(HttpRequestMessage requestMessage, HttpResponseMessage responseMessage) {
        await WaitForReference();
        string requestMethod = requestMessage.Method.Method;
        string requestBody = await GetRequestBodyAsync(requestMessage);
        string responseBody = await responseMessage.Content.ReadAsStringAsync();
        await _accessorJsRef.Value.InvokeVoidAsync("store", requestMessage.RequestUri, requestMethod, requestBody, responseBody);
    }
    public async Task < string > GetAsync(HttpRequestMessage requestMessage) {
        await WaitForReference();
        string requestMethod = requestMessage.Method.Method;
        string requestBody = await GetRequestBodyAsync(requestMessage);
        string result = await _accessorJsRef.Value.InvokeAsync < string > ("get", requestMessage.RequestUri, requestMethod, requestBody);
        return result;
    }
    public async Task RemoveAsync(HttpRequestMessage requestMessage) {
        await WaitForReference();
        string requestMethod = requestMessage.Method.Method;
        string requestBody = await GetRequestBodyAsync(requestMessage);
        await _accessorJsRef.Value.InvokeVoidAsync("remove", requestMessage.RequestUri, requestMethod, requestBody);
    }
    public async Task RemoveAllAsync() {
        await WaitForReference();
        await _accessorJsRef.Value.InvokeVoidAsync("removeAll");
    }
    private static async Task < string > GetRequestBodyAsync(HttpRequestMessage requestMessage) {
        string requestBody = "";
        if (requestMessage.Content is not null) {
            requestBody = await requestMessage.Content.ReadAsStringAsync() ?? "";
        }
        return requestBody;
    }
    #endregion
}


Step 5
Register the helper class in Program.cs
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using MyBlazorWasmApp;
using MyBlazorWasmApp.Helper;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add < App > ("#app");
builder.RootComponents.Add < HeadOutlet > ("head::after");
//Register helper class
builder.Services.AddScoped < CacheStorageAccessor > ();
builder.Services.AddScoped(sp => new HttpClient {
    BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
});
await builder.Build().RunAsync();


Step 6: Run to See output in browser
Output for blazar wasm cache storage using js

Happy Coding!



About HostForLIFE

HostForLIFE is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Month List

Tag cloud

Sign in