使用 golang 重写 nodejs cli
本文最后更新于:2022年1月31日 凌晨
场景
由于吾辈使用 monorepo 管理所有项目,lib 模块初始化的构建时间已经不能接受,所以最近两天吾辈在尝试使用 golang 重写 lib/cli 构建工具 @liuli-util/cli,验证 golang 到底可以做到多快。
@liuli-util/cli 是吾辈创建一个针对于库和 CLI 应用程序打包的零配置构建工具,但也支持一些额外的常用功能,包括生成模板项目、同步配置、部署等。
实现
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 协议 ,转载请注明出处!