node.js rss память не освобождается после снимка кучи - PullRequest
0 голосов
/ 26 апреля 2020

в течение нескольких дней я боролся с утечкой памяти в приложении моего узла, но во время «боя» я заметил, что память rss не освобождается после создания heapdump

версии узла:

$ node --version
v12.16.2

до вывода heapdump из process.memoryUsage():

{
  "rss": 108154880,
  "heapTotal": 36286464,
  "heapUsed": 33339600,
  "external": 1472841
}

и после вывода heapdump:

{
  "rss": 250208256,
  "heapTotal": 36286464,
  "heapUsed": 32413336,
  "external": 31776077
}

, как вы можете заметить rss и external значительно увеличилось (и я проверял, что они остаются примерно на одном уровне после нескольких часов простоя при запуске приложения)

код heapdump:

import { getHeapSnapshot } from 'v8'
import { createGzip } from 'zlib'
import { pipeline as streamPipeline, Readable, Writable, Duplex } from 'stream'
import { promisify } from 'util'
import { createWriteStream } from 'fs'

const pipeline = promisify(streamPipeline)

/**
 * @param date `Date` to use in filename
 * @returns heapdump file name in format `heapdump-<date>-<time>-<pid>.heapsnapshot.gz`
 */
export default async function heapdump (
  date: Date | number,
) {
  if (!(date instanceof Date)) {
    date = new Date(date)
  }

  const filename = `heapdump-${
    date.getUTCFullYear() // year
  }${
    `${date.getUTCMonth() + 1}`.padStart(2, '0') // month
  }${
    `${date.getUTCDate()}`.padStart(2, '0') // day
  }-${
    `${date.getUTCHours()}`.padStart(2, '0') // hour
  }${
    `${date.getUTCMinutes()}`.padStart(2, '0') // minute
  }${
    `${date.getUTCSeconds()}`.padStart(2, '0') // second
  }${
    `${date.getUTCMilliseconds()}`.padStart(3, '0') // millisecond
  }-${
    process.pid
  }.heapsnapshot.gz`

  let heap: Readable
  let gzip: Duplex
  let file: Writable

  await pipeline(
    (heap = getHeapSnapshot()),
    (gzip = createGzip({ level: 9 })),
    (file = createWriteStream(filename)),
  )

  if (!heap.destroyed) {
    heap.destroy()
  }

  if (!gzip.destroyed) {
    gzip.destroy()
  }

  if (!gzip.writableEnded) {
    gzip.end()
  }

  if (!file.writableEnded) {
    file.end()
  }

  return filename
}

и вопрос:

почему не освобождается память? что я тут не так делаю?

...