前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Deno、Node.js、Bun、Deno Deploy... 速度大 PK!最后赢家是它?

Deno、Node.js、Bun、Deno Deploy... 速度大 PK!最后赢家是它?

作者头像
五月君
发布2024-03-18 17:52:33
3650
发布2024-03-18 17:52:33
举报
文章被收录于专栏:Nodejs技术栈

最近我写了一篇关于如何在 Deno 运行时Deno DeployNode.jsBunCloudflare Workers 下让 oak 框架工作的文章,我开始思考它们之间是否会有性能差异。嗯,我找到了答案。

方法和过程

我在 JavaScript/TypeScript 领域看过很多基准测试,并且几乎每一个都被反复辩论过优劣。我相信某些人会对我的方法和过程提出异议,但我想做一些我认为公平的事情。

我对该领域中其他基准测试的一项批评是,它们不能全面评估真实世界的性能和影响。虽然我的测试代码很简单,但我确实想确保它具有一些你在真实应用中期望利用的功能。它需要 oak 框架来确定每个响应的 “类型” 并设置内容标头。这很可能是使用 oak 框架的人们经常使用的功能。它还具有一个错误处理中间件,这很可能是您在真实世界应用中会发现的功能。

以下是我为 Deno CLI、Bun 和 Node.js 的每个测试使用的测试代码:

代码语言:javascript
复制
import { Application } from "@oak/oak/application";
import { Router } from "@oak/oak/router";
import { isHttpError } from "@oak/commons/http_errors";

const router = new Router();

router.get("/", (ctx, next) => {
  ctx.response.body = { hello: "world" };
  return next();
});

const app = new Application();

app.use(async (context, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  context.response.headers.set("X-Response-Time", `${ms}ms`);
});

app.use(async (context, next) => {
  try {
    await next();
  } catch (err) {
    if (isHttpError(err)) {
      context.response.status = err.status;
      const { message, status, stack } = err;
      if (context.request.accepts("json")) {
        context.response.body = { message, status, stack };
        context.response.type = "json";
      } else {
        context.response.body = `${status} ${message}\n\n${stack ?? ""}`;
        context.response.type = "text/plain";
      }
    } else {
      console.log(err);
      throw err;
    }
  }
});

app.use(router.routes());
app.use(router.allowedMethods());

app.addEventListener("listen", ({ hostname, port, secure }) => {
  console.log(
    `Listening on: ${secure ? "https" : "http"}://${hostname}:${port}`,
  );
});

app.listen({ port: 8080 });

对于 Deno Deploy,为了访问 JSR 并解决与 oak 的动态导入相关的回归问题,我不得不重写导入语句:

代码语言:javascript
复制
import { Application, Router } from "jsr:@oak/oak@14.2";
import { isHttpError } from "jsr:@oak/commons@0.7/http_errors";

值得注意的是,如果我没有使用 Deploy Playground 功能,而是部署了一个发布在 GitHub 上的本地 Deno 项目,我可以使用 deno add 将 JSR 依赖项添加到项目中,它们将在导入映射中具有相同的别名。

至于 Cloudflare Workers,我不得不将最后一行从 app.listen({ port: 8080 }); 改为:

代码语言:javascript
复制
export default { fetch: app.fetch };

此外,Cloudflare Worker 从未生成 “listen” 事件,因此该代码是多余的,但我为了完整性而包含了它。

对于 Deno 运行时、Bun 和 Node.js,我在我配备了 Apple M1 Pro 的笔记本电脑上进行了接近的测试,该笔记本有 14 英寸屏幕,配备了 32GB 内存,运行的是 Sonoma 14.2.1。我在同一台机器上运行了服务器和负载发生器。

我在测试时使用了最新版本的 Deno 运行时(v1.41.2)和 Bun(v1.0.30)。对于 Node.js,我使用了当前的 LTS 版本(v20.11.1)和我的运行时管理工具 asdf(v21.6.2)中可用的最新版本。

对于 Deno Deploy,我将代码部署为 Deploy Playground,对于 Cloudflare Workers,我使用 wrangler 部署了一个工作器,没有进行任何调整。我位于墨尔本,使用的是 Telstra NBN,平均下载速度为 99.16 Mbps,上传速度为 18.90 Mbps,平均 ping 时间为 19 毫秒。

对于每次测试运行,我使用了在 Node.js 18.12.1 上运行的 autocannon CLI 版本 7.15.0。我还使用了相同的测试配置:

代码语言:javascript
复制
autocannon -c 100 -d 10 -p 10

这是 100 个并发连接,10 个管线化请求,持续时间为 10 秒。

我对每个目标运行了多次测试,以确保每次运行没有明显不同,而且确实如此。我的结果是我为每个目标进行的最后一次测试运行。

当我查看 Deno Deploy 与 Cloudflare Workers 的结果时,发现了性能上的明显差异,我感到很好奇,因此我对边缘运行时进行了不同配置的测试,以查看是否具有相同的性能特征。在这个中等配置中,我使用了以下测试:

代码语言:javascript
复制
autocannon -c 100 -d 10

这是 100 个并发连接,没有流水线化,持续时间为 10 秒。

结果

以下是代表我的基准测试结果的表格和图表。

延迟

延迟越低越好,它衡量的是单个请求接收到完整响应的时间。

本地托管
边缘托管

高负载

中等负载

每秒请求数

请求数越高越好,代表每秒处理的平均请求数。

本地托管
边缘托管

高负载

中等负载

观察

Deno 运行时

对我个人而言,Deno 的结果并没有什么意外。即使考虑了 oak 的开销,它仍然表现出色。它也非常一致,延迟的标准偏差为 ±1.28 毫秒。

我对 Deno 的开发者体验非常熟悉,即使加入了 JSR,它也没有让我失望。它 “仅能工作”。

Bun

我对 Bun 的了解不多,但当我使用 Deno 时,Bun 开始出现时,人们对其速度之快进行了大量夸赞。在我看来,与许多其他基准测试相比,我认为这次是一个更“现实”的测试,Bun 更快。再次说,这并不让我特别惊讶,因为他们非常专注于这一点。

话虽如此,平均延迟为 12.17 毫秒,而 Deno 的平均延迟为 13.54 毫秒,对我来说是一个强有力的指标,表明它在边缘上获得了微弱的胜利。运行 oak 的 Bun 比 Deno 快 10%,但我仍然认为在做出决定时,您必须考虑其他因素,因为这种收益可能最终是微不足道的。

总体而言,Bun 的开发者体验非常棒。与 Deno 一样,使用 TypeScript 的零配置成本非常棒。此外,通过 JSR,在代码中我能够获得所有智能提示。而且通过 bunx jsr add,我能够添加我的依赖项,而不必触碰其他配置文件。

Node.js

显然,Node.js 与 Deno 和 Bun 之间存在性能差距。在我看过的其他基准测试中,Node.js 的开发人员经常指出正在使用较旧版本的 Node.js。虽然这是一个有效的观点,但您还必须考虑人们在生产中可能运行的情况。Node.js 有一个历史遗留问题,人们更新得很慢。

话虽如此,您可以看到 Node.js 团队一直在努力改进 Node.js 的性能。我相信,如果我回到 Node.js 18,性能差距会更大。

因此,虽然 Bun 比 Deno 快 10%,这可能只是微不足道的胜利,但是 Bun 和 Deno 每个请求的平均速度至少比最新的 Node.js 快两倍,这更难以忽视。

如果我是您,而且我正在将 Node.js 用作生态系统中的某种形式的 API 服务器,我会诚实地看待其他运行时。这并不是对 Node.js 生态系统或团队的轻视,这在一定程度上反映了更大的生态系统能够发展的现实。

就开发者体验而言,还有很多工作要做。较大的 Node.js 生态系统解决了许多摩擦点,实际上,我使用的 npx jsr add 来安装软件包使整个过程非常轻松,我没有试图弄清楚如何在项目中使用 TypeScript。我还知道我需要在 package.json 中添加 "type": "module",才能够使用 index.js 而不是 index.mjs。

Deno Deploy 和 Cloudflare Workers

我对 Deno Deploy 和 Cloudflare Workers 进行了与本地情况相同的负载测试,即相当大的负载。看到两个平台之间的请求时间存在很大的性能差距,这让我重新审视了我的方法和方法。

这让我对两种情况都进行了一些比较温和的负载测试,结果也让我有些惊讶。

我从中得出的观察是:

  • 这两种负载测试都相当不真实。从单一来源达到大约 1000 - 6000 个请求每秒是非常不现实的。虽然对于某些工作负载,每秒处理那么多事务可能是现实的,但它们肯定会在地理上分布,并且特别是对于边缘平台来说这一点很重要。
  • 我注意到 Deno Deploy 在测试期间只扩展到了两个隔离体(运行时处理程序)。我怀疑这也是高负载和中等负载之间性能差异的一个重要因素。我进行了一些其他的临时运行,尝试了不同的流水线和请求之间的排列组合,发现高流水线可能会影响 Deploy 的性能,但这似乎主要是一个总体容量的门槛。
  • 在未达到 “扩展” 阈值时,Deno Deploy 比 Cloudflare Workers 要快得多。
  • Cloudflare Workers 在高级别的事务上规模化,性能几乎没有下降。
  • 在高负载测试中,Deno Deploy 实际上在 62k 个请求中出现了 8 次错误。

从开发者体验的角度来看,我再次可能对 Deno Deploy 有偏见。对于许多工作负载,您所需要的只是 Deno 运行时和推送到 GitHub。在这种情况下,我只是使用了 Deploy 的 playground 功能,这意味着我甚至没有在本地做任何事情。

我以前并不熟悉 Cloudflare Workers 的开发者体验,直到我将 oak 转换为在其上运行。我对它的组织方式非常印象深刻。虽然存在更多的“样板文件”,但有良好的工具可以将其抽象化。

获胜者是...

JavaScript 和 TypeScript 生态系统。我们正处于一个选择很多的时代,这实际上是非常好的,因为创新就发生在这里。

另外,如果您从我的测试中获得了什么,那就是对于大多数工作负载来说,要做出性能不佳的决定实际上是非常困难的。即使 Node.js LTS 也可以处理 24k 个请求每秒。

我心中的另一个赢家是边缘计算。很明显,无论是 Deno Deploy 还是 Cloudflare Workers,它们都是在边缘托管工作负载的理想选择。它们非常低摩擦,并且给您带来了许多除无服务器外的优势。

我想我也学到了 oak 并不那么糟糕。

作者 | Kitson P. Kelly

翻译、整理 | 五月君

原文 https://kitsonkelly.com/posts/http-speed#deno-deploy-and-cloudflare-workers

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-03-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Nodejs技术栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 方法和过程
  • 结果
    • 延迟
      • 本地托管
      • 边缘托管
    • 每秒请求数
      • 本地托管
      • 边缘托管
  • 观察
    • Deno 运行时
      • Bun
        • Node.js
          • Deno Deploy 和 Cloudflare Workers
            • 获胜者是...
            相关产品与服务
            腾讯云服务器利旧
            云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档