编程技术文章分享与教程

网站首页 > 技术文章 正文

多线程 Web 并非不可能。 而 WASM 就是 AWSM

hmc789 2024-11-23 16:27:43 技术文章 2 ℃

在大多数情况下,当今网络上的人们只是希望他们的网站能够正常工作。在过去的 5 到 8 年里,网络发展得如此之快。有些人甚至没有意识到网站变得多么复杂,以及性能是现代网络发展的一个重要因素。对于所有纯后端开发人员来说,前端开发不仅仅是像 2000 年代那样拖放/即插即用 HTML 代码。请继续阅读。这也适用于你!

问题

我们今天所知道的大多数网络都是在 JavaScript 上运行的。即使您使用 TypeScript 编写代码,它最终仍会转译为 JavaScript,因为浏览器无法立即理解 TypeScript;但那是另一次谈话了。为什么这是个问题?要回答这个问题,您必须了解浏览器实际上是如何读取给定网站上的代码的。因此,请考虑以下内容(提示 Bill Nye)。

浏览器固有地有一个单独的线程来运行一个网站。这一直是这样,但大多数人没有意识到实际上发生了多少会减慢他们的网站并影响性能的情况。在简单的 Google 图片搜索中查看浏览器上必须发生的所有事情的这张图片(下图)。这完全在浏览器的主线程上,我相信您在搜索 Google 图片时已经注意到,加载一个充满图片的简单页面有多慢。

这个问题并不止于此。再次检查图像。这几乎没有运行 JavaScript,并且正在运行的 JavaScript 正在使用微任务模式(这对于帮助处理异步任务和顺序任务非常有用)。Google 图片搜索中发生的很多事情都是painting在浏览器加载可视层时发生的。这种渲染是一项非常繁重的任务,最终会在主线程中占用更多空间,从而使其陷入困境,几乎没有空间来容纳像 JavaScript 这样的其他东西。

那么给了什么?我该如何解决这个问题?

这里有很多可用于解决方案的选项。让我们先来看看那些显而易见的。

  1. 缩小你的代码。— 这可能不是很明显,并不能解决所有问题,但是您的代码在缩小状态下更优化,可以比非缩小代码运行得稍好
  2. AOT 编译——许多较新的框架(如 Angular)可以访问 AOT 编译器,并允许在浏览器接收代码之前对其进行预编译,从而使较小的任务更容易运行,因为它不必在下载 JS 时对其进行编译文件。

现在,很多人通常不会在他们的工具链中使用的不太明显的选项。

  1. Workers—— WebWorkers、ServiceWorkers,甚至SharedWorkers(检查对你的浏览器的支持——safari 没有正式支持 SharedWorker API)——都是我们在浏览器中使用 JavaScript 时应该争取的选项
  2. WebAssembly (WASM) — 这是过去 3 到 5 年的一项相当新的技术。很少有关于此的文档或堆栈溢出文章,但它是跨应用程序可共享业务逻辑和功能的未来。

继续阅读以获取有关这两个的更多信息

各类工人

我可以在没有视觉辅助的情况下解释工人的最好方法是使用设计模式。Angular、React、Vue,这些都有可用的模式,它们都知道允许代码分离,利用服务层来获取数据/执行业务逻辑。我知道这可能对你们中的许多人没有帮助,但是如果您正在探索工人,那么您可能已经深入了解语法和编码。

因此,对于工人来说,使用它们有一些注意事项。最大的问题,也许是 JavaScript 开发人员难以理解的问题,是无法访问 DOM 或全局对象,如documentor window。因此,这阻止了许多开发人员在日常代码中使用它们。另一件事是它们没有加载到浏览器的主线程上,您必须通过在单独的线程中向它们发送消息来与它们通信才能执行任务。这种模式让很多人感到困惑。我会为你分解这个。

首先,在主线程中添加一个专门的工作者。假设这就像userprofile.js您正在提取个人资料信息。

使用 LitElement 和 WebWorker 的示例

在上面的示例中,这将繁重的 API 任务卸载到工作线程,让主线程完成加载 UI 其余部分的工作。这也很有用,因为它可以防止线程阻塞 UI,保持 UI 流畅运行。这是一个非常基本的示例,但更复杂的示例包括生成多个 worker、导入脚本、利用模块、真正使您的 worker 有用,以便您可以真正仅将它们用于业务逻辑。

这个例子中使用了 WebWorkers,但我上面提到了另外两个工人——这就是它们的区别:

所有人都在自己的线程上运行主线程。

  1. WebWorkers — 在网站实例运行时运行。
  2. SharedWorkers — 检查支持,并非所有浏览器都支持它们。它们本质上是共享的 WebWorker。它们在网站运行时运行,但它们可以跨多个选项卡或窗口共享一个实例。
  3. ServiceWorkers——注册后在后台运行。即使网站关闭也可以运行,但浏览器仍在运行(有点像 chrome 和 google 日历通知关闭)。

WebAssembly (WASM)

好吧。现在到高级的东西。WebAssembly。首先,它是什么?

WebAssembly 是一个可共享的编译目标,可以跨多个浏览器或上下文使用。那是什么意思?好吧,它是一个编译目标,所以它没有被编写

等待。哇哇哇。你是什?么意思?

对不起。这是我进行过的真实对话,我正在这里玩耍。

所以 WebAssembly 是从 C、C++、C#、Java、Python、Rust 等高级语言编译而来的(Rust 非常适合 WASM),甚至是一种非常基于 TypeScript 的语言,称为 AssemblyScript。所以。这意味着您为后端编写了复杂的业务逻辑以处理文档、渲染游戏、处理安全密钥甚至访问服务器上的本机功能或与数据库接口的任何语言。这些现在都可以编译以*.wasm供前端浏览器使用和使用。

你为什么问?出色地。为什么不?多年来,人们一直在构建本地桌面应用程序,其中包含大量复杂的业务逻辑和预先优化的代码,那么为什么我们需要从头开始重写它们以便它们可以在 Web 上使用呢?许多公司这样做是为了将他们的传统桌面应用程序转移到未来并在网络上可用:

整个Adob??e Creative Cloud Suite几乎已被提升并转移到浏览器中工作。

像Figma这样的网站是在浏览器中使用 C++ 和 WASM 的先驱,将他们的应用程序带到了现代网络的最前沿。

和游戏。Unity使 WASM 变得庞大且易于开发人员使用,以便为 Web 和本地桌面制作他们的游戏。

可以使用 WASM 的应用程序的列表不胜枚举。但并非每个站点都需要它。

WASM 确实在功能手机等低端设备上大放异彩,甚至是旧款 iPhone 或 Android 手机,它们的功能可能不如旗舰手机。由于 WASM 是提前编译的,因此它一开始就进行了预优化。JavaScript 可能需要执行几次才能高效运行(浏览器会优化 JS,但不会立即发生)。当有人使用功能手机并尝试加载性能不正常的网站或使用非常繁重的 JavaScript 来完成任务时,这一点尤其明显。

WASM 与 Workers 有什么区别?

好吧,如果您已经走到了这一步,我不一定要回答这个问题,但我认为公平地说,WASM 仍然必须由 JavaScript 实例化。WASM 并不是要取代JavaScript,而是要与之配对;如果你做对了,你将从工作线程执行和实例化流到你的 WASM,使其远离 UI 线程(主线程)。

所以当你编译成 WASM 时,JavaScript 仍然需要说明如何执行它,以及它需要如何调用 WASM 文件中的函数。

以上是关于 WASM 的 MDN 文章。我强烈建议你通过它。

由于 WASM 是经过编译的,因此其中的函数必须事先由编译器公开,并且可供 JavaScript 访问。这个过程可以通过一个名为的工具来完成emscripten——这是允许 WASM 工作的魔法酱。Empscripten 会输出一个 js 文件和一个 .wasm 文件,它们都是混淆的和不可读的。JS 是将您从 WASM 公开的函数关联到 javascript 的胶水代码,您将其导入到您的代码中。另一种方法是直接从 WASM 文件流式传输到您的 javascript 中,并WebAssembly.instantiateStreaming()在浏览器 API 中以这种方式调用函数。

反正。这篇 WASM 文章非常复杂,对于这篇已经很长的博文来说太复杂了。它本身值得一篇文章。

我可能已经跳过了一些。对于那个很抱歉。但本质上,WASM 就像你的 JavaScript 可以调用和执行的共享库,但由于它是预编译的,因此它可以使用浏览器中的典型 JavaScript API 上可能不可用的库或函数进行编译(如原生蓝牙、wifi、处理器、实际硬件、渲染 API、数据库,不胜枚举)。

如果您想了解更多关于 WASM 的信息,我将在下面发布一些链接。

包起来

这是一篇冗长的文章。对于那个很抱歉。这里没有很多代码片段,只有关于工人的代码片段。请继续关注,我正在撰写一篇关于 WebAssembly 的文章和一个基本用例,它可能适用于任何项目,但可以从中获得巨大的性能提升。

记住。使一切工作化。WASM 就是 AWSM。

Tags:

标签列表
最新留言