【问题标题】:Blazor WebAssembly deserializing is much slower than even the download? What is wrong?Blazor WebAssembly 反序列化甚至比下载慢得多?怎么了?
【发布时间】:2020-11-24 23:30:34
【问题描述】:

在我的 Blazor 应用程序中,我有一个具有类似方法的组件。 (我已经用其中的代码替换了 GetFromJsonAsync 调用,以缩小缓慢的部分。)

  private async Task GetData()
  {
      IsLoading = true;
      string url = $".../api/v1/Foo";  // will return a 1.5 MB JSON array
      var client = clientFactory.CreateClient("MyNamedClient");

      Console.WriteLine($"starting");

      List<Foo> results;

      Task<HttpResponseMessage> taskResponse = client.GetAsync(url, HttpCompletionOption.ResponseContentRead, default);

      var sw = Stopwatch.StartNew();
      using (HttpResponseMessage response = await taskResponse)
      {
        
        response.EnsureSuccessStatusCode();
        var content = response.Content!;

        if (content == null)
        {
          throw new ArgumentNullException(nameof(content));
        }
        
        string contentString = await content.ReadAsStringAsync();

        sw.Stop();
        Console.WriteLine($"Read string: {sw.Elapsed}");
        sw.Restart();

        results = System.Text.Json.JsonSerializer.Deserialize<List<Foo>>(contentString);

      }

      sw.Stop();
      Console.WriteLine($"Deserialize: {sw.Elapsed}");
      
      StateHasChanged();
      IsLoading = false;

我的 1.5 MB 下载需要 1-6 秒,但其余操作(在此期间 UI 被阻止)需要 10-30 秒。 这只是在ReadFromJsonAsync(内部调用System.Text.Json.JsonSerializer.Deserialize)中的缓慢反序列化,还是这里发生了其他事情我怎样才能提高获取这么多数据集的效率(虽然我认为它并没有那么大!)

为了简化,我已经注释掉了绑定到 Results 的任何内容,而我只是有一个绑定到 IsLoading 的指示器。这告诉我更新 DOM 或渲染没有问题。

当我在自动化集成测试中尝试同一组代码时,只需要 3 秒左右。 WebAssembly 在反序列化方面真的那么慢吗?如果是这样,是在我的网站上到处检索非常小的数据集的唯一解决方案吗?这对我来说似乎不对。

这是运行上述代码所产生的浏览器控制台日志:

VM1131:1 Fetch finished loading: GET "https://localhost:5001/api/v1/Foo".
read string 00:00:05.5464300
Deserialize: 00:00:15.4109950
L: GC_MAJOR_SWEEP: major size: 3232K in use: 28547K
L: GC_MAJOR: (LOS overflow) time 18.49ms, stw 18.50ms los size: 2048K in use: 187K
L: GC_MINOR: (LOS overflow) time 0.33ms, stw 0.37ms promoted 0K major size: 3232K in use: 2014K los size: 2048K in use: 187K

无论如何,这是 Chrome 性能图表。绿色是下载,橙色是“执行微任务”,我认为这意味着 WebAssembly 工作。

【问题讨论】:

  • 看看Newtonsoft是否更好
  • 我已经编辑了示例以使其更清晰,并且实际上将下载与反序列化分开。
  • 答案可能是“是的,它很慢”,它作为解释的 IL 代码运行。迁移到 .net 5 时可能会有一些小的改进,但直到我们获得 AoT 编译才会接近“正常”速度。不知道那是什么时间线。
  • 关于什么使它变慢或如何解决的任何建议?是检索较小数据块的唯一方法吗?有什么方法可以使序列化更简单,或者以某种方式处理未序列化/结构化数据较少的数据?
  • 1.5 MB 是大量的 JSON 下载和反序列化。你绝对需要下载那么多数据吗?可以分页吗?出于好奇,JavaScript 需要多长时间来反序列化它?

标签: performance blazor blazor-client-side blazor-webassembly


【解决方案1】:

还是这里有其他事情发生?

看起来是这样的。您没有说明您使用什么硬件,但在我的桌面(i7)上,我可以在

所以,从 localhost 下载 5 秒已经很奇怪了。您的设置有问题。

一个 MCVE:

  • 从 Wasm 托管模板开始
  • 让控制器返回 ~17000 个项目(原为 5 个)以获得 ~1.5 MB
  • 将代码放入 FetchData OnInit() 中,将 Foo 替换为 WeatherForecast
  • 不要尝试全部渲染。

看看你得到了什么结果。

【讨论】:

  • 我确实有 7-12 秒的时间返回 17000 项(约 1.6 MB)的 WeatherForecast。 (在 localhost 上的下载时间约为 20 毫秒。)使用默认的 await Http.GetFromJsonAsync&lt;WeatherForecast[]&gt;("WeatherForecast"); 所以这似乎与我在原始问题中稍微复杂一点的情况的时间一致。 (仅供参考,我还通过 NuGet 将 System.Text.Json 更新到 v 5.0.0-preview.7,但没有太大帮助。)
  • (另外,我将有效负载增加到 5 MB,这需要 23-27 秒。)
猜你喜欢
  • 1970-01-01
  • 2013-08-16
  • 1970-01-01
  • 2022-11-25
  • 2013-07-04
  • 2021-09-22
  • 2020-08-30
  • 2021-09-21
  • 1970-01-01
相关资源
最近更新 更多