需要改善Blazor Wasm在CPU密集计算方面的性能

9
我有一个C# WinForms应用程序,我一直在将其转换为Blazor Wasm。它需要在大多数用户输入后执行一组计算密集型计算(即没有IO或UI交互)。这些计算涉及重复调用一组25-35个C#类对象中的多个方法(30-50次),具体取决于情况。相同的计算代码在WinForms和Blazor应用程序中运行。
我发现在Blazor下性能下降了约20倍(例如,在WinForms中为350ms,在Blazor中为7000ms)。这种程度的性能下降是否合理?其中很大一部分是否与在浏览器中运行有关?是否Blazor Wasm也是其中的一部分?我已经确认性能下降分布在整个计算过程中,而不是在某些隔离的地方。是否有任何方法可以显着减少性能下降?如果可能的话,执行计算的对象可以放在类库中是否有帮助?
我已在GitHub的AspNetCore讨论区发布了此问题,但没有得到回应。我使用的是VS Community 2019 v16.8.2,AspNetCore 5.0和Chrome v。
谢谢。史蒂夫

2
是的,这是预期的性能下降。Blazor wasm目前以解释器模式运行(尽管在不久的将来可能会改变),这意味着只有运行时本身编译为wasm。然后该运行时会下载并解释来自您的dll的IL,与直接将程序集编译为WASM的情况相比,这相当慢。很快就应该可以直接编译为WASM,并且应该提供一些性能改进(尽管它仍无法达到本机.NET应用程序的水平)。 - Evk
唉,我希望那不是答案。我有相当多的时间等待编译实现,但如果能对改进后的性能与本机.NET进行一些比较,那将会很有帮助。2-3倍的速度下降可能是可行的(也许需要做出一些逻辑上的妥协),但5倍以上可能会成为一个绊脚石。无论如何,感谢您的观点。 - Steve Rehling
很难确定(对我来说)这将实现什么样的加速,实际上可能只会慢3倍。然而,即使是 WASM 本身支持多线程,在某些浏览器中也支持(并且更多将最终支持),但 Blazor WASM 也不支持多线程。虽然直接编译为 wasm 已经在即将到来 - 但我不知道近期有关多线程的任何计划。对于 CPU 密集型计算,这可能会为本机 .NET 提供更多功率。 - Evk
我知道这篇文章已经发布几周了,但我想确认一下你的计算是否涉及任何异步调用 - 你有在等待什么吗?在计算过程中,你是否更新了用户界面?你是否对用户输入进行了去抖动处理,以防止在异步情况下在单个线程上同时运行计算? - Mister Magoo
这些计算并不是按照你的要求执行的,它们只是纯粹的CPU处理。有一个已实例化的单例控制着这些计算,通过调用一组大约40个对象中的各种方法来进行计算。所有这些对象都在启动时被实例化并在每次需要进行新一轮计算时被重复使用。 - Steve Rehling
7个回答

3
这是对这个问题的非常晚的回应,但是 Web Worker 是否可以帮助解决这个问题呢?这将为表格带来一些多线程的能力。我无法自己实现它,但有一个帮助库似乎可以很容易地将其引入到 Blazor 中:https://github.com/Tewr/BlazorWorker 在原生 JavaScript 中,您可以通过 Navigator Api 访问浏览器的核心数:Navigator Api

const coreCount = window.navigator.hardwareConcurrency;
console.log(`Your computer has ${coreCount} cores!`);


谢谢您的建议。我能理解它对某些需求可能有帮助,但在我的情况下,计算需要完全同步。 - Steve Rehling

2

1
Blazor Wasm不支持多线程,而像鼠标事件处理这样频繁的操作在浏览器中处理起来很“沉重”。尝试将操作处理程序推入队列并在后台处理。

如果直接编译不能提高性能,我恐怕需要从用户的角度彻底重新考虑它的工作方式。将事物推入队列进行后台处理并不是一个解决方案。无论如何,感谢您的想法。 - Steve Rehling

1
如果您有 .NET 后端,可以轻松地在那里执行代码。只需几毫秒的开销,您就可以获得几乎与以前相同的性能。使用相同的语言在两侧之间有一个好处。

2
我很感激您的想法,也许我需要走这条路。我的希望是出于几个原因使/保持应用程序仅为客户端,其中主要原因是能够声称用户的信息完全保存在他们的计算机上。从技术上讲,该应用程序将其持久化在IndexedDB中。如果由于性能问题而证明这是不可行的,那么我将考虑采用客户端-服务器模式。 - Steve Rehling

0

将在浏览器中运行的程序与在操作系统本地运行的程序进行比较可能是不公平的。我更愿意将Blazor与JavaScript进行比较,因为它们都在浏览器上运行。在浏览器中运行的程序的优点是它可以在大多数设备上运行,从个人电脑到大多数移动设备。此外,它以MSIL的形式存在,比JavaScript更难逆向工程。然而,这也有一个代价,即性能(MSIL在Mono -> WASM -> Native)。


谢谢您的观点。我正在比较WinForms和Blazor的性能,因为我有那段代码,而不是JS版本的代码。最终,我需要在Blazor下实现更好的性能。 - Steve Rehling

0

Blazor 有两种托管模型:Blazor 客户端和 Blazor 服务器模型。详情请参见:Blazor 托管模型 如果您使用 Blazor 客户端,我会预期出现这样的退化,但在 Blazor 服务器中不会。


0
如果它是纯计算,为什么不使用 WASM 语言 (例如 Rust),然后从 JavaScript 中调用它呢?正如 Josef 指出的那样,您还可以使用服务器端 Blazor 或简单地调用 Web 服务端点。

感谢大家的建议。已经有相当数量的C#代码编写和调试,因此转换到其他语言并不是一个非常有吸引力的选择。转向Blazor Server模型是一个选项,尽管我一直在避免这样做,因为它增加了额外的变量。出于这两个原因,我开始走Blazor Wasm的道路,即C#和仅客户端。 - Steve Rehling
1
我希望编译后的Blazor能够足够好用。我已经在AspNetCore GitHub(https://github.com/dotnet/runtime/issues/45363)上发布了一个问题,以了解那些管理开发的人有什么话要说。 - Steve Rehling

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接