UNPKG

@nearform/heap-profiler

Version:

Heap dump, sample profiler and allocation timeline generator for Node.

90 lines (72 loc) 2.05 kB
'use strict' const { Session } = require('inspector') const SonicBoom = require('sonic-boom') const { ensurePromiseCallback, destinationFile, validateDestinationFile } = require('./utils') module.exports = function generateHeapSnapshot(options, cb) { /* istanbul ignore if */ if (typeof options === 'function') { cb = options options = null } // Prepare the context const [callback, promise] = ensurePromiseCallback(cb) const { destination, runGC } = Object.assign({ destination: destinationFile('heapsnapshot'), runGC: false }, options) const session = new Session() let error = null let handled = false if (typeof destination !== 'string' || destination.length === 0) { throw new Error('The destination option must be a non empty string') } validateDestinationFile(destination, err => { if (err) { return callback(err) } const writer = new SonicBoom({ dest: destination }) function onWriterEnd(err) { /* istanbul ignore if */ if (handled) { return } handled = true session.disconnect() callback(err || error, destination) } writer.on('error', onWriterEnd) writer.on('close', onWriterEnd) if (runGC && typeof global.gc === 'function') { try { global.gc() } catch (e) { error = e writer.end() return promise } } // Start the session session.connect() // Prepare chunk appending session.on('HeapProfiler.addHeapSnapshotChunk', m => { // A write failed, discard all the rest /* istanbul ignore if */ if (error) { return } try { writer.write(m.params.chunk) } catch (e) { /* istanbul ignore next */ error = e } }) // Request heap snapshot session.post('HeapProfiler.takeHeapSnapshot', null, (err, r) => { /* istanbul ignore next */ if (err && !error) { error = err } // Cleanup writer.end() }) }) return promise }