Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ async function cmd (argv, banner = defaultBanner) {
visualizeOnly: 'visualize-only',
visualizeCpuProfile: 'visualize-cpu-profile',
collectOnly: 'collect-only',
collectDelay: 'collect-delay',
kernelTracing: 'kernel-tracing',
kernelTracingDebug: 'kernel-tracing-debug',
treeDebug: 'tree-debug',
Expand Down
6 changes: 6 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ with relevant outputs.

Default: false

#### `collectDelay` (number)

Specify a delay(ms) before collecting data.

Default: 0

#### `mapFrames` (function)

A custom mapping function that receives
Expand Down
10 changes: 8 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ async function zeroEks (args) {
args.pathToNodeBinary = pathTo('node')
}

args.collectDelay = args.collectDelay || 0

validate(args)
const { collectOnly, visualizeOnly, writeTicks, treeDebug, mapFrames, visualizeCpuProfile } = args
const { collectOnly, visualizeOnly, writeTicks, treeDebug, mapFrames, visualizeCpuProfile, collectDelay } = args

let incompatibleOptions = 0
if (collectOnly) incompatibleOptions += 1
Expand Down Expand Up @@ -63,6 +65,10 @@ async function zeroEks (args) {
return folder
}

if (collectDelay) {
debug('data collection will be delayed by ' + collectDelay + ' ms')
}

try {
const file = generateFlamegraph({ ...args, ticks, inlined, pid, folder })
return file
Expand Down Expand Up @@ -145,7 +151,7 @@ async function visualize ({ visualizeOnly, treeDebug, workingDir, title, mapFram
name = name || meta.name

const ticks = (srcType === 'v8')
? await v8LogToTicks(src, pathToNodeBinary)
? await v8LogToTicks(src, { pathToNodeBinary })
: traceStacksToTicks(src)

if (treeDebug === true) {
Expand Down
18 changes: 13 additions & 5 deletions lib/v8-log-to-ticks.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ const nodeMajorV = Number(process.versions.node.split('.')[0])

module.exports = wrapper

async function wrapper (isolateLogPath, node) {
async function wrapper (isolateLogPath, options) {
const normalised = await prepareForPreprocess(isolateLogPath)
return v8LogToTicks(normalised, node)
return v8LogToTicks(normalised, options)
}

// 1. Filter because long lines make the --preprocess crash. Filter them beforehand,
Expand Down Expand Up @@ -67,9 +67,9 @@ function fixLines (line) {
}
}

function v8LogToTicks (isolateLogPath, node) {
function v8LogToTicks (isolateLogPath, options) {
const isJson = extname(isolateLogPath) === '.json'
const sp = isJson || spawn(node, [
const sp = isJson || spawn(options.pathToNodeBinary, [
'--prof-process', '--preprocess', isolateLogPath
], { stdio: ['ignore', 'pipe', 'pipe'] })

Expand Down Expand Up @@ -119,10 +119,18 @@ function v8LogToTicks (isolateLogPath, node) {
close()
})

const firstTick = []
const delayMs = options.collectDelay * 1000;
const tickStream = parse('ticks.*', (tick) => {
const addr = tick.s.filter((n, i) => i % 2 === 0)
var stack = addr.map((n) => codes[n]).filter(Boolean)
ticks.push(stack.reverse())
if (firstTick.length === 0) {
firstTick.push(tick.tm)
}
// Compare ticks to first for collectDelay
if (tick.tm > (firstTick[0] + delayMs)) {
ticks.push(stack.reverse())
}
})

pump(srcStream, tickStream, (err) => {
Expand Down
4 changes: 2 additions & 2 deletions platform/v8.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const {
module.exports = v8

async function v8 (args) {
const { status, outputDir, workingDir, name, onPort, pathToNodeBinary } = args
const { status, outputDir, workingDir, name, onPort, pathToNodeBinary, collectDelay } = args

let proc = spawn(pathToNodeBinary, [
'--prof',
Expand Down Expand Up @@ -114,7 +114,7 @@ async function v8 (args) {
const isolateLogPath = path.join(folder, isolateLog)
await renameSafe(path.join(args.workingDir, isolateLog), isolateLogPath)
return {
ticks: await v8LogToTicks(isolateLogPath, pathToNodeBinary),
ticks: await v8LogToTicks(isolateLogPath, { pathToNodeBinary, collectDelay }),
inlined: inlined,
pid: proc.pid,
folder: folder
Expand Down
6 changes: 6 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,12 @@ with relevant outputs.

Default: false

### --collect-delay

Delay the collection of stacks by a specified time(ms) relative to the first entry.

Default: 0

### --visualize-only

Supply a path to a profile folder to build or rebuild visualization
Expand Down
6 changes: 6 additions & 0 deletions schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@
},
"P": {
"type": "string"
},
"collect-delay": {
"type": "number"
},
"collectDelay": {
"type": "number"
},
"kernelTracing": {
"type": "boolean"
Expand Down
3 changes: 3 additions & 0 deletions usage.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@

--collect-only Do not process captured stacks into a flamegraph.

--collect-delay Specify a delay(ms) before collecting data.


--visualize-only <dir> Build or rebuild flamegraph using the output dir.
Counterpart to --collect-only.

Expand Down