使用 golang 重写 nodejs cli

本文最后更新于:2022年1月31日 凌晨

场景

由于吾辈使用 monorepo 管理所有项目,lib 模块初始化的构建时间已经不能接受,所以最近两天吾辈在尝试使用 golang 重写 lib/cli 构建工具 @liuli-util/cli,验证 golang 到底可以做到多快。

@liuli-util/cli 是吾辈创建一个针对于库和 CLI 应用程序打包的零配置构建工具,但也支持一些额外的常用功能,包括生成模板项目、同步配置、部署等。

1643537400132

实现

saki npm,所有测试均在 liuli-tools 完成,它是一个有 44 个模块组成的 monorepo,其中有 28 个需要构建。

整体基于 esbuild 来重写 liuli-cli 的 build 命令,支持 build lib/cli 以及自定义目标。下面是一些吾辈在重写之后做的测试,证明使用 golang 可以大幅度提高 lib 构建性能,它是如此快速以至于有可能将它放在 postinstall 中。

命令均使用 time seq 10 | xargs -i <cmd> 重复执行 10 次

saki build

基于 esbuild 构建 lib 或 cli 程序,它非常快。

saki build lib # 构建 lib
saki build cli # 构建 cli

性能测试

下面两个 cli 都基于 esbuild 实现的构建,但后者真实运行时间很长,因为 nodejs 本身加载代码也需要时间(而且很慢)。

下载二进制文件安装

$ saki build lib

real    0m0.647s
user    0m0.060s
sys     0m0.183s
# 平均 64.7ms/次

$ saki build cli

real    0m2.831s
user    0m0.106s
sys     0m0.275s
# 平均 283.1ms/次

npm 全局安装

$ saki build lib

real    0m2.724s
user    0m0.482s
sys     0m1.665s
# 平均 272.4ms/次

$ saki build cli

real    0m4.622s
user    0m0.587s
sys     0m1.438s
# 平均 462.2ms/次

liuli-cli

$ liuli-cli build lib

real    0m6.882s
user    0m0.648s
sys     0m1.364s
# 平均 688.2ms/次

$ liuli-cli build cli

real    0m8.687s
user    0m0.587s
sys     0m1.333s
# 平均 868.7ms/次

saki run

一个 pnpm --filter . run 的替代命令,尝试提高多线程运行命令的效率。

saki run setup # 在所有模块运行 setup 命令(如果有这个命令)
saki run --filter libs/* setup # 在所有匹配 libs/* 的模块中运行 setup 命令
# 使用 --filter 数组
saki run --filter libs/* --filter apps/* setup # 或者使用 , 分割
saki run --filter libs/*,apps/* setup

性能测试

pnpm + liuli-cli + dts

$ pnpm --filter . run setup

real    4m49.648s
user    0m0.593s
sys     0m1.391s
# 平均 1034.4ms/个

pnpm + liuli-cli

$ pnpm --filter . run setup

real    1m3.847s
user    0m0.468s
sys     0m1.484s
# 平均 228ms/个

saki + liuli-cli

$ saki run setup

real    1m19.657s
user    0m0.497s
sys     0m1.494s
# 平均 284.4ms/个

pnpm + saki(几乎是使用 js 工具链难以想象的)

$ pnpm --filter . run setup

real    0m16.168s
user    0m0.435s
sys     0m1.590s
# 平均 57.7ms/个

npm saki

$ saki run setup

real    0m17.545s
user    0m0.651s
sys     0m1.618s
# 平均 62.6ms/个

下载二进制文件安装 saki

$ saki run setup

real    0m13.742s
user    0m0.046s
sys     0m0.258s
# 平均 49.0ms/个

Windows 下使用 git bash –filter 参数请用 "" 包裹

结论

目前来看,builder 提高的比较明显,而 run 则几乎和 node 相差无几(有时候甚至更慢了)。

吾辈可能会继续尝试使用 golang 重写更多的前端基础工具,nodejs 的性能目前而言看起来并不能用。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!