Gatsby 的开源并行处理
为了帮助更大的 Gatsby 生态系统缩短从提交到部署所需的时间,今天我刚刚提交了一个新鲜的Pull 请求,作为我对 Gatsby 开源项目的第一个较大贡献。
新的gatsby-parallel-runner插件建立在 Gatsby 项目中一些现有工作的基础上,允许插件和 Gatsby 的核心部分通过将工作委托给大量无服务器功能池来并行化某些任务。
Gatsby Cloud 率先采用了这种方法,我希望通过这个插件,我们能够开启一种更通用的并行化方法。虽然它目前还处于早期开发阶段,但我的目标是,未来有一天,它能够在任何 CI/CD 环境中使用,并赋能生态系统中的插件开发者,让他们能够在某个任务非常适合并行化时,构建对并行化的支持。
盖茨比和“外部工作”
不到一个月前,Gatsby 团队的 Ward Peeters 提交了一个Pull 请求,请求“通过 ipc 启用外部作业”。该 Pull 请求背后的理念是,gatsby build
编排父进程可以 forkgatsby build
并确保ENABLE_GATSBY_EXTERNAL_JOBS
设置了名为“外部作业”的环境变量,而不是直接运行。完成后,某些作业将通过 Node 的 IPC 协议作为“外部作业”发送到父进程,以便父编排器能够高效地并行执行这些作业。
nodejs 本身是单线程的,因此 Gatsby 中任何 CPU 密集型作业都只能利用一个 CPU 核心,但这种基于 ipc 的委派开辟了利用外部工作进程进行并行化的可能性。
目前唯一与此挂钩的插件是gatsby-plugin-sharp
用于图像转换的插件。在 Netlify,我们经常看到图像转换是 Gatsby 网站构建速度下降的一大原因,因为在单线程构建中进行大量图像处理效率非常低。
开源 Gatsby 流程到目前为止还没有为 Gatsby 提供任何可以帮助您利用外部作业的编排器实现,而这正是我们的新gatsby-parallel-runner
帮助所在。
盖茨比平行跑者
我一直很喜欢构建这个新的 Gatsby 插件,它可以作为替代的构建命令。一旦安装在项目中,你就可以运行gatsby-parallel-runner
而不是gatsby build
。
它开箱即用,内置基于 Google Cloud Functions 的 Sharp 图像插件的并行化实现。它包含一个简单的脚本,只需一个命令即可在 Google Cloud 项目中设置您自己的函数和队列。它具有可扩展性,因此社区可以轻松添加实际执行层的替代实现。AWS Lambda 函数或 Node.js 集群实现是理想的选择。它也应该易于与需要添加图像处理之外的外部作业的新插件配合使用。
我希望这可以为构建并行化生态系统中的更多创新铺平道路——当然,我们看到在 Netlify 自己的构建层中添加更通用的形式有很多机会。
我们的理念始终是保持构建层的根本开放——我们的核心构建镜像和新的构建插件层始终是开源的。我们始终坚信,构建工具领域健康的开源生态系统对于整个 JAMstack 产品线的发展至关重要。因此,我们很高兴将这个项目回馈给开源社区。
我在 Netlify 的构建环境中使用官方 Gatsby 图像基准测试库运行了一些基准测试(有和没有),gatsby-parallel-runner
并且很高兴看到它的gatsby-parallel-runnner
表现始终优于正常gatsby build
命令:
从清除缓存中运行 3 次gatsby build
:
Run 1:
11:10:27 PM: success Generating image thumbnails - 351.218s - 3234/3234 9.21/s
Run 2:
1:45:43 PM: success Generating image thumbnails - 384.171s - 3234/3234 8.42/s
Run 3:
11:18:22 PM: success Generating image thumbnails - 322.853s - 3234/3234 10.02/s
Avg time for image generation: 352.747s
从清除缓存中运行 6 次gatsby-parallel-runner
:
Run 1:
10:51:31 PM: success Generating image thumbnails - 158.438s - 3234/3234 20.41/s
Run 2:
5:33:33 PM: success Generating image thumbnails - 68.016s - 3234/3234 47.55/s
Run 3:
3:03:48 AM: success Generating image thumbnails - 75.731s - 3234/3234 42.70/s
Run 4:
10:54:47 PM: success Generating image thumbnails - 64.478s - 3234/3234 50.16/s
Run 5:
10:58:31 PM: success Generating image thumbnails - 66.021s - 3234/3234 48.98/s
Run 6:
11:01:58 PM: success Generating image thumbnails - 71.416s - 3234/3234 45.28/s
Avg time for image generation: 84.017s
由于 Google 致力于扩大并发函数执行的数量,因此部署函数后的第一次运行比后续运行要慢一些,但即便如此,在最坏的情况下,它的速度仍然比标准 Gatsby 构建命令快两倍以上。
平均而言 - 即使包含初始异常值 - 并行运行器的速度也比单线程运行时提高了 4.2 倍以上。
出于好奇,我在 Gatsby Cloud 上重复了相同的基准测试:
Run 1:
03:02:38 AM: success Generating image thumbnails - 98.472s - 3234/3234 32.84/s
Run 2:
07:34:53 AM: success Generating image thumbnails - 328.141s - 3234/3234 9.86/s
Run 3:
22:19:50 PM: success Generating image thumbnails - 85.101s - 3234/3234 38.00/s
Run 4:
22:34:22 PM: success Generating image thumbnails - 134.721s - 3234/3234 24.01/s
Run 5:
23:02:37 PM: success Generating image thumbnails - 82.822s - 3234/3234 39.05/s
Run 6:
23:07:31 PM: success Generating image thumbnails - 60.532s - 3234/3234 53.43/s
Avg time for image generation: 131.631s
与我基于 Netlify 的测试相比,这些测试的构建时间差异更大,虽然平均速度是单线程构建速度的两倍多,但在我运行的测试中,开源并行运行器的性能明显更佳。因此,希望 Gatsby Cloud 团队也能从研究此实现背后的源代码中受益。
设置
在你的 gatsby 项目中安装:
npm i gatsby-parallel-runner
要与 Google Cloud 一起使用,请在 shell 中设置相关的环境变量:
export GOOGLE_APPLICATION_CREDENTIALS=~/path/to/your/google-credentials.json
export TOPIC=parallel-runner-topic
部署云功能:
npx gatsby-parallel-runner deploy
然后使用并行运行器而不是默认gatsby build
命令运行您的 Gatsby 构建。
npx gatsby-parallel-runner