Bun批量生成文件哈希时内存暴涨问题及优化咨询
解决Bun批量生成文件哈希时内存飙升的问题
你的代码核心问题很明确:一是把每个文件完整读进内存生成ArrayBuffer,二是forEach会同时发起所有文件的异步读取请求,导致大量文件内容同时驻留内存,直接拉高内存占用。哪怕单个ArrayBuffer会被垃圾回收(GC)处理,并行加载的情况下根本等不及回收就已经堆满内存了。
1. 如何释放内存?
JS没有手动强制释放内存的API,得靠GC自动回收,但你可以帮GC加速处理:
- 在
hashFile里处理完哈希后,手动解除对buffer的引用,让GC能快速识别这块内存可回收:async function hashFile(file: string) { let buffer = await Bun.file(file).arrayBuffer(); const hash = Bun.hash.crc32(buffer); buffer = null; // 清空引用,帮助GC回收内存 return hash; } - 更关键的是避免同时加载过多文件:把
forEach改成for...of串行处理,同一时间只有一个文件的内容在内存里,处理完就会被GC收走,内存占用会稳定在单个文件的大小左右。
2. 更优的实现方案
最优方案是流式处理文件——不用把整个文件读进内存,而是分块读取、分块计算哈希,这样内存占用只跟缓冲区大小有关,几乎可以忽略。Bun支持流式处理文件,结合它的哈希API就能实现:
流式哈希代码示例
async function hashFileStream(filePath: string) { const file = Bun.file(filePath); const hash = Bun.hash.crc32.create(); // 创建流式哈希实例 const stream = file.stream(); // 逐块读取文件并更新哈希 for await (const chunk of stream) { hash.update(chunk); } return hash.digest(); // 生成最终哈希值 } // 串行处理所有文件,内存占用稳定 const files: string[] = ["path to file1", "path to file2"]; const hashes: number[] = []; for (const file of files) { const hash = await hashFileStream(file); console.log( "Memory usage: ", Math.trunc(process.memoryUsage.rss() / 1024 / 1024), "MB" ); hashes.push(hash); }
兼顾速度与内存:控制并发数
如果不想完全串行,想加快处理速度,可以限制同时处理的文件数量(比如一次处理3个),手动控制并发:
async function processFilesWithLimit(files: string[], limit: number) { const hashes: number[] = []; const runningTasks: Promise<void>[] = []; for (const file of files) { const task = (async () => { const hash = await hashFileStream(file); hashes.push(hash); console.log( "Memory usage: ", Math.trunc(process.memoryUsage.rss() / 1024 / 1024), "MB" ); })(); runningTasks.push(task); // 达到并发上限时,等待一个任务完成再继续 if (runningTasks.length >= limit) { await Promise.race(runningTasks); // 移除已完成的任务 runningTasks.splice(runningTasks.findIndex(t => t.status === "fulfilled"), 1); } } // 等待剩余所有任务完成 await Promise.all(runningTasks); return hashes; } // 调用示例:一次处理3个文件 processFilesWithLimit(files, 3);
内容的提问来源于stack exchange,提问作者Fernando Crespo
相关产品推荐
相关产品推荐

