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

Node.js分块提取数据内存占用异常:为何与原文件大小一致?

分块提取数据仍占用全量内存的原因分析

问题背景

原文件大小2.24MB,仅需提取其中0.2MB的数据,通过分块处理试图降低内存占用,但内存测量结果显示占用量仍接近2.2MB,实际提取出的buffer大小仅0.19MB。

用户提供的代码

数据提取函数

function foo(url,sectionToWatchStart,sectionToWatchEnd ) {
  let isDataSectionFound = false;

  return new Promise((resolve, reject) => {
    let buffer= "";
    https
      .get(url, function (response) {
        response.on("data", function (chunk) {
          if (chunk.includes(sectionToWatchStart)) isDataSectionFound = true;

          if (isDataSectionFound) {
            buffer += chunk;

            if (chunk.includes(sectionToWatchEnd)) {
              isDataSectionFound = false;
            }
          }
        });
        response.on("end", function () {
          
          resolve(buffer); // the measure size of buffer variable is just 0.19MB
          
        });
      })
      .on("error", function (error) {
        console.error(error);
        reject();
      });
  });
}

内存测量工具函数

// Util Func to measure the size:
const mesurMemory = async () => {
  const initialMemoryUsage = process.memoryUsage().heapUsed;
  const res = await foo();
  const finalMemoryUsage = process.memoryUsage().heapUsed;
  const memoryUsageForCode = finalMemoryUsage - initialMemoryUsage;
  console.log(`Memory usage for code: ${memoryUsageForCode / (1024 * 1024)}MB`);
};

核心原因

  • Node.js HTTP响应默认加载全量数据:哪怕你只需要部分内容,https.get会把整个2.24MB的响应数据全部接收并缓存到内存里,你的代码只是从中筛选出了目标片段,但全量数据已经被加载,内存自然降不下来。
  • 字符串拼接的额外内存开销:JS里字符串是不可变的,每次buffer += chunk都会生成新的字符串,旧的字符串不会立刻被垃圾回收,这会产生额外的内存碎片和占用。
  • 内存测量时机不对:在end事件触发时,全量响应的缓存还没被垃圾回收,此时测量的堆内存包含了这些未释放的数据,导致结果偏高。

解决办法

  1. 找到目标片段后立刻终止响应:避免继续加载剩余数据,直接节省内存
if (chunk.includes(sectionToWatchEnd)) {
  isDataSectionFound = false;
  response.destroy(); // 终止响应,停止接收后续数据
}
  1. 用Buffer替代字符串拼接:Buffer的拼接效率更高,减少内存碎片
function foo(url,sectionToWatchStart,sectionToWatchEnd ) {
  let isDataSectionFound = false;

  return new Promise((resolve, reject) => {
    const buffer = []; // 改用数组存Buffer片段
    https
      .get(url, function (response) {
        response.on("data", function (chunk) {
          if (chunk.includes(sectionToWatchStart)) isDataSectionFound = true;

          if (isDataSectionFound) {
            buffer.push(chunk);

            if (chunk.includes(sectionToWatchEnd)) {
              isDataSectionFound = false;
              // 拼接Buffer并转为字符串
              const result = Buffer.concat(buffer).toString();
              resolve(result);
              response.destroy(); // 终止响应
            }
          }
        });
        response.on("end", function () {
          resolve(Buffer.concat(buffer).toString());
        });
      })
      .on("error", function (error) {
        console.error(error);
        reject();
      });
  });
}
  1. 延迟测量内存,触发垃圾回收:给垃圾回收机制时间清理无用数据(需Node.js启动时加--expose-gc参数)
const mesurMemory = async () => {
  const initialMemoryUsage = process.memoryUsage().heapUsed;
  const res = await foo();
  // 手动触发垃圾回收
  if (typeof global.gc === 'function') {
    global.gc();
  }
  const finalMemoryUsage = process.memoryUsage().heapUsed;
  const memoryUsageForCode = finalMemoryUsage - initialMemoryUsage;
  console.log(`Memory usage for code: ${memoryUsageForCode / (1024 * 1024)}MB`);
};

内容的提问来源于stack exchange,提问作者benny hassan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 01:16:00