递归获取文件夹大小,使用 go,足够快,可以跑在 node 中

3,192 阅读2分钟

go-get-folder-size

递归获取文件夹大小,使用 go,足够快,可以跑在 node 中


仓库

Github 👉 go-get-folder-size


特性

  • 🦕 二进制 go
  • 🦖 原生 node
  • 🐊 wasm go

动机

想要快速知道文件夹大小,但 nodejs 实现的 get-folder-size 是慢的,所以用 go 实现了递归获取文件夹大小,能跑在 nodejs 中。

具体可见 issue 👉 get-folder-size/issues/22

例如我们同样用 cli 计算 184,046 个文件,35,185 个文件夹,共 7 GB 左右的目录

原生 node,大概 11.5s 👇

node-get.gif

go 重写后,只需要 1.7s 👇

go-get.gif

不过这里 nodeget-folder-size 累加操作没上 worker-pool 线程池的,没有发挥 node 完全的性能。

不过就算上了线程池估计也打不过 gogoroutine。即使能打过,文件数量级再上一个层次后也会被 go 赶超。


使用

npm

install

npm install go-get-folder-size

cli

# Binary go, fastest
npx go-get-folder-size

program

import {
	getFolderSize,
	getFolderSizeBin,
	getFolderSizeWasm
} from 'go-get-folder-size'

const base = './' // 你想要获取的目录

await getFolderSizeBin(base) // 二进制 go,最快

await getFolderSize(base) // 原生 node

await getFolderSizeWasm(base) // Wasm go,最慢 🥵

go

install

go install github.com/markthree/go-get-folder-size

cli

go-get-folder-size

program

go get github.com/markthree/go-get-folder-size
package main

import (
	getFolderSize "github.com/markthree/go-get-folder-size/src"
)

func main() {
	size, err := getFolderSize.Parallel("./") // 并发计算,超级快
}

提示

  • wasm 出奇的比原生 node 要慢 🫣
  • 目前该包被使用在组织内的本地项目管理器中,首次获取项目大小优化到 1s 内 👉 x-pm

灵感来源

go-get-folder-size 的实现灵感来自 👇


原理

wasm

如何在 node 中调用 go 呢,大家第一时间可能就想到 go 编译成 wasm 嘛,然后再用 node 去调用 wasm 👇

微信截图_20230207202529.png

确实可以,但是在这个例子中,wasm 反而比 node 原生还要慢很多 😅

很神奇,有知道怎么回事的靓仔靓女可以评论区说下为什么 🫡

二进制

另外一种方式就是将 go 编译成二进制执行文件,node 再起子进程调用二进制执行文件。

微信截图_20230207202928.png

不过这种方式仍然存在资源浪费的问题,因为跑完二进制后我们的进程就被销毁了,而创建和销毁进程是很浪费资源的。

理想状态下,应该是只起一个子进程,然后进行 ipc 通讯 👇

微信截图_20230207203910.png

go-get-folder-size 目前只实现了第一种单纯的调用,未来可能会像 gluon-framework/gluon 一样起常驻进程,提供 websocketstdio 等通讯方式。

尾声

如果对后续其他的开源感兴趣,也欢迎关注 👇

文中提到的我在管理的仓库 👇