runtime: Loading `appsettings.json` with 600 lines of "data" is very slow in blazor wasm

Describe the bug

When adding an appsettings.json to a dotnet core wasm project with 600 lines of “data”, then loading this via IOptions is very slow. The performance depends on the size of the JSON. I.e. smaller configs are faster. Maybe the issue is related to deserialization.

To Reproduce

What I did

  • dotnet new blazorwasm
  • Stripped out anything but counter
  • Added a new service which makes use of IOptions to access configuration data
  • Register dependency to service and options in Program.cs
  • Inject my service to Counter.razor

What happens

Upon accessing Counter-page the client spends ~7 seconds in the constructor of MicStepsService:

image

Delay is caused when accessing the config value:

 _configValue = config.Value;

Stripping down configuration reduces the delay according to config size. I also tried to change the code to read data from embedded resource using Newtonsoft.Json. This fixed the issue as well:

var assembly = Assembly.GetExecutingAssembly();
var resourceName = "NRZMyk.Services.MicSteps.json";

using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
   var result = reader.ReadToEnd();
   var micSteps = JsonConvert
     .DeserializeObject<Dictionary<SpeciesTestingMethod, Dictionary<AntifungalAgent, List<MicStep>>>>(result);
}

Repro project

https://github.com/markusrt/SlowWasmAppSettings

Exceptions (if any)

no Exceptions

Further technical details

  • ASP.NET Core version: 5.0.301

  • The IDE (VS / VS Code/ VS4Mac) you’re running on, and its version: Microsoft Visual Studio Enterprise 2019, Version 16.10.1

  • Browser: Chrome Version 96.0.4664.45 (Offizieller Build) (64-Bit)

  • Include the output of dotnet --info:

    dotnet --info Output
    $ dotnet --info
    .NET SDK (gemäß "global.json"):
     Version:   5.0.301
    Commit:    ef17233f86
    
    Laufzeitumgebung:
    OS Name:     Windows
    OS Version:  10.0.19042
    OS Platform: Windows
    RID:         win10-x64
    Base Path:   C:\Program Files\dotnet\sdk\5.0.301\
    
    Host (useful for support):
    Version: 5.0.7
    Commit:  556582d964
    
    .NET SDKs installed:
    3.1.300 [C:\Program Files\dotnet\sdk]
    5.0.301 [C:\Program Files\dotnet\sdk]
    
    .NET runtimes installed:
    Microsoft.AspNetCore.All 2.1.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
    Microsoft.AspNetCore.All 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
    Microsoft.AspNetCore.App 2.1.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.AspNetCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.AspNetCore.App 3.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.AspNetCore.App 3.1.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.AspNetCore.App 5.0.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.NETCore.App 2.1.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 3.1.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 3.1.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 5.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.WindowsDesktop.App 3.1.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
    Microsoft.WindowsDesktop.App 3.1.16 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
    Microsoft.WindowsDesktop.App 5.0.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
    
    To install additional .NET runtimes or SDKs:
    https://aka.ms/dotnet-download
    

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 25 (16 by maintainers)

Most upvoted comments

OK, I did some more investigation, and it looks like the hot reload issue above is a red-herring. The slowness happens in dotnet run for me as well.

I narrowed it down to this line:

    builder.Configuration.Bind(options);

Specifically it is the Bind method. Changing that code to:

    var c = builder.Configuration;
    global::System.Console.WriteLine($"here {DateTime.Now}");
    JsonStreamConfigurationProvider provider = (JsonStreamConfigurationProvider)((IConfigurationRoot)c).Providers.First();
    provider.TryGet("Breakpoint:MicSteps:Vitek:Micafungin:0:Title", out string val);
    global::System.Console.WriteLine($"here2 {DateTime.Now} {val}");
    c.Bind(options);
    global::System.Console.WriteLine($"done {DateTime.Now}");

Produces:

info: SlowWasmAppSettings.MyCode.MicStepsService[0]
      configType_factory__validations: Microsoft.Extensions.Options.IValidateOptions`1[SlowWasmAppSettings.MyCode.BreakpointSettings][] - 0
blazor.webassembly.js:1 here 12/8/2021 5:42:40 PM
blazor.webassembly.js:1 here2 12/8/2021 5:42:40 PM ≤0,06
blazor.webassembly.js:1 done 12/8/2021 5:42:44 PM
blazor.webassembly.js:1 info: SlowWasmAppSettings.MyCode.MicStepsService[0]
      config.Value after: 3999ms
blazor.webassembly.js:1 info: SlowWasmAppSettings.MyCode.MicStepsService[0]
      Found: 517 values in total
blazor.webassembly.js:1 info: SlowWasmAppSettings.MyCode.MicStepsService[0]
      Exiting constructor after: 4001ms

Configuration binder works using Reflection - and there are over 1,000 name value pairs in that json file. So yes, I can imagine this being slow on interpreted WASM.

Hi @javiercn thanks for the prompt reply.

.NET 6.0 works like a charm:

image

I updated my repro-project. Now I only need to update my real project which is still on NET 3.1 😅