Extracting cpu profile and memory dump from a live Express.js app
Still in the same vibe of How I solved a memory leak in a NodeJS worker, I’m going to describe how I created an entrypoint on Express.js to extract cpu profile logs and heap dump using v8-profiler.
The first problem that I’ve found was a segfault when trying to generate the heap dumps, that I promptly noticed in the issue tracker that it is a compatibility bug related to node 8.x. Following a user’s suggestion, I replaced the v8-profile by v8-profile-node8 for now. Inspite of the horrible documentation and random v8-profiler is pretty handy.
Here is my code. Enjoy:
import * as profiler from 'v8-profiler-node8';
if (process.env.ENABLE_PROFILE) {
router.get('/admin/memory_profile', (_req, res) => {
var snapshot = profiler.takeSnapshot();
let contentDisposition = `attachment; filename="${process.pid}-${Date.now()}.heapsnapshot"`
res.setHeader('Content-type', 'application/pdf');
res.setHeader('Content-disposition', contentDisposition);
snapshot.export().pipe(res).on('finish', () => {
console.log('finished sending dump')
snapshot.delete()
})
})
// Only allow one capture per thread
let capturingCpuProfile = false;
router.get('/admin/cpu_profile', (_req, res) => {
if (capturingCpuProfile) {
return res.status(400).send('CPU profile being captured')
}
capturingCpuProfile = true
profiler.startProfiling();
// Let it capture the cpu log for 30 seconds and then downloads the file
setTimeout(() => {
capturingCpuProfile = false
const profile = profiler.stopProfiling();
let contentDisposition = `attachment; filename="${process.pid}-${Date.now()}.cpuprofile"`
res.setHeader('Content-type', 'application/pdf');
res.setHeader('Content-disposition', contentDisposition);
profile.export().pipe(res)
.on('finish', function() {
profile.delete();
});
}, 30000)
})
}
I used that ENABLE_PROFILE
environment variable because I dont want to let it available on production as default. It’s a good idea to prevent unauthorized access too.
After downloading the files, just load them on chrome dev tools. For memory leak debugging, take a look at my previous post.
Caveats
- Generating a memory dump uses a lot of memory, so make sure that the process is using less than half of the available memory.
- The memory dump file must have the extension
.heapdump
- The cpu profile log must have the extension
.cpuprofile