debugging-aid
Version:
Experimental tools for debugging Node.js apps without pausing
76 lines (67 loc) • 1.67 kB
JavaScript
// testcase
setInterval(function inint () {
suspect()
}, 0)
function suspect () {
const t0 = Date.now()
while (t0 === Date.now()) {
culprit()
}
}
function culprit () {
Math.sqrt(Math.pow(1111111111111, 22222))
}
// -----
const inspector = require('inspector')
const util = require('util')
const session = new inspector.Session()
const postAsync = util.promisify(session.post.bind(session))
const delay = (x = 10) => new Promise((re) => setTimeout(re, x))
let ranking = Object.create(null)
const rank = (key, hits) => {
if (!ranking[key]) {
ranking[key] = 0
}
ranking[key] += hits
}
function evaluateRanking () {
const oldRanking = ranking
const entries = Object.entries(oldRanking).sort((a, b) => {
return b[1] - a[1]
})
ranking = entries
.slice(0, Math.max(10, Math.ceil(entries.length / 10)))
.reduce((acc, entry) => {
acc[entry[0]] = entry[1]
return acc
}, Object.create(null))
return ranking
}
session.connect()
session.post('Profiler.enable', () => {
setInterval(oneProfile, 50)
setInterval(() => {
console.log(evaluateRanking())
}, 10000)
console.log('enable')
})
const signature = ({ url, functionName, lineNumber }) => {
if (url) {
return `${functionName}@${url}:${lineNumber}`
} else {
return functionName
}
}
async function oneProfile () {
try {
await postAsync('Profiler.start')
await delay(10)
const result = await postAsync('Profiler.stop')
result.profile.nodes.forEach((fn) => {
if (fn.hitCount > 0 && fn.callFrame.functionName !== '(program)') {
rank(signature(fn.callFrame), fn.hitCount)
}
})
} catch (e) {
}
}