You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 02:45:29