如何在使用 WebAssembly 进行大量计算时保持反应式 UI?
Posted
技术标签:
【中文标题】如何在使用 WebAssembly 进行大量计算时保持反应式 UI?【英文标题】:How to keep a reactive UI while doing heavy computation with WebAssembly? 【发布时间】:2020-08-14 13:17:54 【问题描述】:我使用 C++ 库在加载时进行大量图像处理,使用 emscripten 编译并嵌入到 Angular 应用程序中。 此代码将 UI 冻结几秒钟,这对用户来说绝不是好事。
我猜这里有两个选项
将繁重的计算拆分为多个异步调用 使用threads (WebWorkers)虽然我不确定每种方法的可行性,具体取决于计算代码。
各自的优点/不便之处是什么?使用 JS/WASM 处理繁重计算的常用方法是什么?
【问题讨论】:
【参考方案1】:我都做了。
只是 异步 仍将在主线程上,因此它对您的情况没有任何好处。但是,如果您可以将处理分成更小的块并随着时间的推移将它们提供给requestIdleCallback,它会非常有效。这样做的缺点是您无法真正控制它何时(如果有的话)完成。根据输出的重要性,它可能不是最适合您的。好处是您确实可以访问所有 API,而不仅仅是 Web 工作者可用的 API。这是example of implementation 的“拆分成更小的块并将其提供给 requestIdleCallback”和here's how you use it。
使用网络工作线程有一个很大的好处是可以完全释放主线程,这可以让你更快地得到结果。缺点是你只能访问 web worker API,你必须找到一种方法将你的输出传回主线程(如果有必要),它仍然会占用大量 CPU(这意味着当主线程线程在技术上是“免费的”,它可能仍然会变慢)。如果您可以将任务拆分成更小的块,您甚至可以生成多个线程并获得更流畅/更快的用户体验。
主线程
可能会冻结页面(或者需要很长时间/永远不会完成) 让您可以访问所有 API 更容易开始,稍微复杂一点,您会进入闲置直到紧急的设计 将数据传入/传出不会成为瓶颈网络工作者
释放主线程(但可能仍会减慢整个客户端的速度) 并非所有 API 都可用 一旦掌握了与主线程通信的句柄,就非常简单了 如果您尝试派生更多的工人并行工作,就会变得复杂 如果您的输出不能直接构造为 SharedArray,则传递大量数据可能是一个问题/瓶颈【讨论】:
谢谢!但是,您是在回答我假设的 JS 吗? WebAssembly 可能对此有一些限制?就像在 C++ 中使用requestIdleCallback
一样
@ymoreau 我只知道用于 WebAssembly 的 Rust,但我知道你至少可以从 JS 回调中调用一个 wasm 函数,这样你就可以使用 requestIdleCallback 绑定你的处理块。
这是一个例子,我正在做类似的事情,但对于requestAnimationFrame
:github.com/Sheraff/boids/blob/master/js/…以上是关于如何在使用 WebAssembly 进行大量计算时保持反应式 UI?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 emscripten 生成独立的 WebAssembly
如何在 blazor webassembly 项目中对服务器端控制器中的用户进行身份验证?