inspector: split --cpu-prof-path to --cpu-prof-dir and --cpu-prof-name
To improve the integration of `--cpu-prof` with workers, this patch splits `--cpu-prof-path` into `--cpu-prof-dir` and `--cpu-prof-name`, so when a worker is launched from a thread that enables `--cpu-prof`, if the parent thread sets `--cpu-prof-dir`, then the profile of both thread would be generated to the specified directory. If they end up specifying the same `--cpu-prof-name` the behavior is undefined the last profile will overwritten the first one. PR-URL: https://github.com/nodejs/node/pull/27306 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
parent
a3d1922958
commit
49d3d11ba7
@ -83,8 +83,13 @@ added: REPLACEME
|
|||||||
> Stability: 1 - Experimental
|
> Stability: 1 - Experimental
|
||||||
|
|
||||||
Starts the V8 CPU profiler on start up, and writes the CPU profile to disk
|
Starts the V8 CPU profiler on start up, and writes the CPU profile to disk
|
||||||
before exit. If `--cpu-prof-path` is not specified, the profile will be
|
before exit.
|
||||||
written to `${cwd}/CPU.${yyyymmdd}.${hhmmss}.${pid}.${tid}.${seq}.cpuprofile`.
|
|
||||||
|
If `--cpu-prof-dir` is not specified, the generated profile will be placed
|
||||||
|
in the current working directory.
|
||||||
|
|
||||||
|
If `--cpu-prof-name` is not specified, the generated profile will be
|
||||||
|
named `CPU.${yyyymmdd}.${hhmmss}.${pid}.${tid}.${seq}.cpuprofile`.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ node --cpu-prof index.js
|
$ node --cpu-prof index.js
|
||||||
@ -92,19 +97,24 @@ $ ls *.cpuprofile
|
|||||||
CPU.20190409.202950.15293.0.0.cpuprofile
|
CPU.20190409.202950.15293.0.0.cpuprofile
|
||||||
```
|
```
|
||||||
|
|
||||||
### `--cpu-prof-path`
|
### `--cpu-prof-dir`
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: REPLACEME
|
added: REPLACEME
|
||||||
-->
|
-->
|
||||||
|
|
||||||
> Stability: 1 - Experimental
|
> Stability: 1 - Experimental
|
||||||
|
|
||||||
Location where the CPU profile generated by `--cpu-prof`
|
Specify the directory where the CPU profiles generated by `--cpu-prof` will
|
||||||
should be written to. When used alone, it implies `--cpu-prof`.
|
be placed.
|
||||||
|
|
||||||
```console
|
### `--cpu-prof-name`
|
||||||
$ node --cpu-prof-path /tmp/test.cpuprofile index.js
|
<!-- YAML
|
||||||
```
|
added: REPLACEME
|
||||||
|
-->
|
||||||
|
|
||||||
|
> Stability: 1 - Experimental
|
||||||
|
|
||||||
|
Specify the file name of the CPU profile generated by `--cpu-prof`.
|
||||||
|
|
||||||
### `--enable-fips`
|
### `--enable-fips`
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
|
14
doc/node.1
14
doc/node.1
@ -81,13 +81,17 @@ Print source-able bash completion script for Node.js.
|
|||||||
.It Fl -cpu-prof
|
.It Fl -cpu-prof
|
||||||
Start the V8 CPU profiler on start up, and write the CPU profile to disk
|
Start the V8 CPU profiler on start up, and write the CPU profile to disk
|
||||||
before exit. If
|
before exit. If
|
||||||
.Fl -cpu-prof-path
|
.Fl -cpu-prof-dir
|
||||||
is not specified, the profile will be written to the current working directory.
|
is not specified, the profile will be written to the current working directory
|
||||||
|
with a generated file name.
|
||||||
.
|
.
|
||||||
.It Fl -cpu-prof-path
|
.It Fl -cpu-prof-dir
|
||||||
Path the V8 CPU profile generated with
|
The directory where the CPU profiles generated by
|
||||||
.Fl -cpu-prof
|
.Fl -cpu-prof
|
||||||
will be written to. When used alone, it implies
|
will be placed.
|
||||||
|
.
|
||||||
|
.It Fl -cpu-prof-name
|
||||||
|
File name of the V8 CPU profile generated with
|
||||||
.Fl -cpu-prof
|
.Fl -cpu-prof
|
||||||
.
|
.
|
||||||
.It Fl -enable-fips
|
.It Fl -enable-fips
|
||||||
|
@ -38,6 +38,14 @@
|
|||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
|
||||||
|
#define CWD_BUFSIZE (MAX_PATH * 4)
|
||||||
|
#else
|
||||||
|
#include <climits> // PATH_MAX on Solaris.
|
||||||
|
#define CWD_BUFSIZE (PATH_MAX)
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace node {
|
namespace node {
|
||||||
|
|
||||||
inline v8::Isolate* IsolateData::isolate() const {
|
inline v8::Isolate* IsolateData::isolate() const {
|
||||||
@ -678,6 +686,15 @@ inline void Environment::set_cpu_profile_path(const std::string& path) {
|
|||||||
inline const std::string& Environment::cpu_profile_path() const {
|
inline const std::string& Environment::cpu_profile_path() const {
|
||||||
return cpu_profile_path_;
|
return cpu_profile_path_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void Environment::set_cpu_prof_dir(const std::string& path) {
|
||||||
|
cpu_prof_dir_ = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const std::string& Environment::cpu_prof_dir() const {
|
||||||
|
return cpu_prof_dir_;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // HAVE_INSPECTOR
|
#endif // HAVE_INSPECTOR
|
||||||
|
|
||||||
inline std::shared_ptr<HostPort> Environment::inspector_host_port() {
|
inline std::shared_ptr<HostPort> Environment::inspector_host_port() {
|
||||||
|
18
src/env.cc
18
src/env.cc
@ -845,6 +845,24 @@ void Environment::stop_sub_worker_contexts() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAVE_INSPECTOR
|
||||||
|
|
||||||
|
void Environment::InitializeCPUProfDir(const std::string& dir) {
|
||||||
|
if (!dir.empty()) {
|
||||||
|
cpu_prof_dir_ = dir;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char cwd[CWD_BUFSIZE];
|
||||||
|
size_t size = CWD_BUFSIZE;
|
||||||
|
int err = uv_cwd(cwd, &size);
|
||||||
|
// TODO(joyeecheung): fallback to exec path / argv[0]
|
||||||
|
CHECK_EQ(err, 0);
|
||||||
|
CHECK_GT(size, 0);
|
||||||
|
cpu_prof_dir_ = cwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HAVE_INSPECTOR
|
||||||
|
|
||||||
void MemoryTracker::TrackField(const char* edge_name,
|
void MemoryTracker::TrackField(const char* edge_name,
|
||||||
const CleanupHookCallback& value,
|
const CleanupHookCallback& value,
|
||||||
const char* node_name) {
|
const char* node_name) {
|
||||||
|
@ -1137,6 +1137,11 @@ class Environment : public MemoryRetainer {
|
|||||||
|
|
||||||
inline void set_cpu_profile_path(const std::string& path);
|
inline void set_cpu_profile_path(const std::string& path);
|
||||||
inline const std::string& cpu_profile_path() const;
|
inline const std::string& cpu_profile_path() const;
|
||||||
|
|
||||||
|
inline void set_cpu_prof_dir(const std::string& path);
|
||||||
|
inline const std::string& cpu_prof_dir() const;
|
||||||
|
|
||||||
|
void InitializeCPUProfDir(const std::string& dir);
|
||||||
#endif // HAVE_INSPECTOR
|
#endif // HAVE_INSPECTOR
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -1173,6 +1178,7 @@ class Environment : public MemoryRetainer {
|
|||||||
std::unique_ptr<profiler::V8CoverageConnection> coverage_connection_;
|
std::unique_ptr<profiler::V8CoverageConnection> coverage_connection_;
|
||||||
std::unique_ptr<profiler::V8CpuProfilerConnection> cpu_profiler_connection_;
|
std::unique_ptr<profiler::V8CpuProfilerConnection> cpu_profiler_connection_;
|
||||||
std::string coverage_directory_;
|
std::string coverage_directory_;
|
||||||
|
std::string cpu_prof_dir_;
|
||||||
std::string cpu_profile_path_;
|
std::string cpu_profile_path_;
|
||||||
#endif // HAVE_INSPECTOR
|
#endif // HAVE_INSPECTOR
|
||||||
|
|
||||||
|
@ -318,19 +318,13 @@ void StartCoverageCollection(Environment* env) {
|
|||||||
env->coverage_connection()->Start();
|
env->coverage_connection()->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartCpuProfiling(Environment* env, const std::string& profile_path) {
|
void StartCpuProfiling(Environment* env, const std::string& profile_name) {
|
||||||
std::string path;
|
std::string path = env->cpu_prof_dir() + std::string(kPathSeparator);
|
||||||
if (profile_path.empty()) {
|
if (profile_name.empty()) {
|
||||||
char cwd[CWD_BUFSIZE];
|
|
||||||
size_t size = CWD_BUFSIZE;
|
|
||||||
int err = uv_cwd(cwd, &size);
|
|
||||||
// TODO(joyeecheung): fallback to exec path / argv[0]
|
|
||||||
CHECK_EQ(err, 0);
|
|
||||||
CHECK_GT(size, 0);
|
|
||||||
DiagnosticFilename filename(env, "CPU", "cpuprofile");
|
DiagnosticFilename filename(env, "CPU", "cpuprofile");
|
||||||
path = cwd + std::string(kPathSeparator) + (*filename);
|
path += *filename;
|
||||||
} else {
|
} else {
|
||||||
path = profile_path;
|
path += profile_name;
|
||||||
}
|
}
|
||||||
env->set_cpu_profile_path(std::move(path));
|
env->set_cpu_profile_path(std::move(path));
|
||||||
env->set_cpu_profiler_connection(
|
env->set_cpu_profiler_connection(
|
||||||
|
@ -239,7 +239,8 @@ MaybeLocal<Value> RunBootstrapping(Environment* env) {
|
|||||||
|
|
||||||
#if HAVE_INSPECTOR
|
#if HAVE_INSPECTOR
|
||||||
if (env->options()->cpu_prof) {
|
if (env->options()->cpu_prof) {
|
||||||
profiler::StartCpuProfiling(env, env->options()->cpu_prof_path);
|
env->InitializeCPUProfDir(env->options()->cpu_prof_dir);
|
||||||
|
profiler::StartCpuProfiling(env, env->options()->cpu_prof_name);
|
||||||
}
|
}
|
||||||
#endif // HAVE_INSPECTOR
|
#endif // HAVE_INSPECTOR
|
||||||
|
|
||||||
|
@ -149,6 +149,15 @@ void EnvironmentOptions::CheckOptions(std::vector<std::string>* errors) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_INSPECTOR
|
#if HAVE_INSPECTOR
|
||||||
|
if (!cpu_prof) {
|
||||||
|
if (!cpu_prof_name.empty()) {
|
||||||
|
errors->push_back("--cpu-prof-name must be used with --cpu-prof");
|
||||||
|
}
|
||||||
|
if (!cpu_prof_dir.empty()) {
|
||||||
|
errors->push_back("--cpu-prof-dir must be used with --cpu-prof");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
debug_options_.CheckOptions(errors);
|
debug_options_.CheckOptions(errors);
|
||||||
#endif // HAVE_INSPECTOR
|
#endif // HAVE_INSPECTOR
|
||||||
}
|
}
|
||||||
@ -335,14 +344,17 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
|
|||||||
#if HAVE_INSPECTOR
|
#if HAVE_INSPECTOR
|
||||||
AddOption("--cpu-prof",
|
AddOption("--cpu-prof",
|
||||||
"Start the V8 CPU profiler on start up, and write the CPU profile "
|
"Start the V8 CPU profiler on start up, and write the CPU profile "
|
||||||
"to disk before exit. If --cpu-prof-path is not specified, write "
|
"to disk before exit. If --cpu-prof-dir is not specified, write "
|
||||||
"the profile to the current working directory.",
|
"the profile to the current working directory.",
|
||||||
&EnvironmentOptions::cpu_prof);
|
&EnvironmentOptions::cpu_prof);
|
||||||
AddOption("--cpu-prof-path",
|
AddOption("--cpu-prof-name",
|
||||||
"Path the V8 CPU profile generated with --cpu-prof will be "
|
"specified file name of the V8 CPU profile generated with "
|
||||||
"written to.",
|
"--cpu-prof",
|
||||||
&EnvironmentOptions::cpu_prof_path);
|
&EnvironmentOptions::cpu_prof_name);
|
||||||
Implies("--cpu-prof-path", "--cpu-prof");
|
AddOption("--cpu-prof-dir",
|
||||||
|
"Directory where the V8 profiles generated by --cpu-prof will be "
|
||||||
|
"placed. Does not affect --prof.",
|
||||||
|
&EnvironmentOptions::cpu_prof_dir);
|
||||||
#endif // HAVE_INSPECTOR
|
#endif // HAVE_INSPECTOR
|
||||||
AddOption("--redirect-warnings",
|
AddOption("--redirect-warnings",
|
||||||
"write warnings to file instead of stderr",
|
"write warnings to file instead of stderr",
|
||||||
|
@ -110,7 +110,8 @@ class EnvironmentOptions : public Options {
|
|||||||
bool preserve_symlinks_main = false;
|
bool preserve_symlinks_main = false;
|
||||||
bool prof_process = false;
|
bool prof_process = false;
|
||||||
#if HAVE_INSPECTOR
|
#if HAVE_INSPECTOR
|
||||||
std::string cpu_prof_path;
|
std::string cpu_prof_dir;
|
||||||
|
std::string cpu_prof_name;
|
||||||
bool cpu_prof = false;
|
bool cpu_prof = false;
|
||||||
#endif // HAVE_INSPECTOR
|
#endif // HAVE_INSPECTOR
|
||||||
std::string redirect_warnings;
|
std::string redirect_warnings;
|
||||||
|
7
test/fixtures/workload/fibonacci-worker-argv.js
vendored
Normal file
7
test/fixtures/workload/fibonacci-worker-argv.js
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { Worker } = require('worker_threads');
|
||||||
|
const path = require('path');
|
||||||
|
new Worker(path.join(__dirname, 'fibonacci.js'), {
|
||||||
|
execArgv: ['--cpu-prof']
|
||||||
|
});
|
4
test/fixtures/workload/fibonacci-worker.js
vendored
4
test/fixtures/workload/fibonacci-worker.js
vendored
@ -2,6 +2,4 @@
|
|||||||
|
|
||||||
const { Worker } = require('worker_threads');
|
const { Worker } = require('worker_threads');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
new Worker(path.join(__dirname, 'fibonacci.js'), {
|
new Worker(path.join(__dirname, 'fibonacci.js'));
|
||||||
execArgv: ['--cpu-prof']
|
|
||||||
});
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// This tests that --cpu-prof and --cpu-prof-path works.
|
// This tests that --cpu-prof, --cpu-prof-dir and --cpu-prof-name works.
|
||||||
|
|
||||||
const common = require('../common');
|
const common = require('../common');
|
||||||
if (process.features.debug &&
|
if (process.features.debug &&
|
||||||
@ -27,17 +27,22 @@ function getCpuProfiles(dir) {
|
|||||||
.map((file) => path.join(dir, file));
|
.map((file) => path.join(dir, file));
|
||||||
}
|
}
|
||||||
|
|
||||||
function verifyFrames(output, file, suffix) {
|
function getFrames(output, file, suffix) {
|
||||||
const data = fs.readFileSync(file, 'utf8');
|
const data = fs.readFileSync(file, 'utf8');
|
||||||
const profile = JSON.parse(data);
|
const profile = JSON.parse(data);
|
||||||
const frames = profile.nodes.filter((i) => {
|
const frames = profile.nodes.filter((i) => {
|
||||||
const frame = i.callFrame;
|
const frame = i.callFrame;
|
||||||
return frame.url.endsWith(suffix);
|
return frame.url.endsWith(suffix);
|
||||||
});
|
});
|
||||||
|
return { frames, nodes: profile.nodes };
|
||||||
|
}
|
||||||
|
|
||||||
|
function verifyFrames(output, file, suffix) {
|
||||||
|
const { frames, nodes } = getFrames(output, file, suffix);
|
||||||
if (frames.length === 0) {
|
if (frames.length === 0) {
|
||||||
// Show native debug output and the profile for debugging.
|
// Show native debug output and the profile for debugging.
|
||||||
console.log(output.stderr.toString());
|
console.log(output.stderr.toString());
|
||||||
console.log(profile.nodes);
|
console.log(nodes);
|
||||||
}
|
}
|
||||||
assert.notDeepStrictEqual(frames, []);
|
assert.notDeepStrictEqual(frames, []);
|
||||||
}
|
}
|
||||||
@ -118,11 +123,11 @@ const env = {
|
|||||||
verifyFrames(output, profiles[0], 'fibonacci-sigint.js');
|
verifyFrames(output, profiles[0], 'fibonacci-sigint.js');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Outputs CPU profile from worker.
|
// Outputs CPU profile from worker when execArgv is set.
|
||||||
{
|
{
|
||||||
tmpdir.refresh();
|
tmpdir.refresh();
|
||||||
const output = spawnSync(process.execPath, [
|
const output = spawnSync(process.execPath, [
|
||||||
fixtures.path('workload', 'fibonacci-worker.js'),
|
fixtures.path('workload', 'fibonacci-worker-argv.js'),
|
||||||
], {
|
], {
|
||||||
cwd: tmpdir.path,
|
cwd: tmpdir.path,
|
||||||
env
|
env
|
||||||
@ -136,56 +141,55 @@ const env = {
|
|||||||
verifyFrames(output, profiles[0], 'fibonacci.js');
|
verifyFrames(output, profiles[0], 'fibonacci.js');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output to specified --cpu-prof-path without --cpu-prof
|
// --cpu-prof-name without --cpu-prof
|
||||||
{
|
{
|
||||||
tmpdir.refresh();
|
tmpdir.refresh();
|
||||||
const file = path.join(tmpdir.path, 'test.cpuprofile');
|
|
||||||
const output = spawnSync(process.execPath, [
|
const output = spawnSync(process.execPath, [
|
||||||
'--cpu-prof-path',
|
'--cpu-prof-name',
|
||||||
file,
|
'test.cpuprofile',
|
||||||
fixtures.path('workload', 'fibonacci.js'),
|
fixtures.path('workload', 'fibonacci.js'),
|
||||||
], {
|
], {
|
||||||
cwd: tmpdir.path,
|
cwd: tmpdir.path,
|
||||||
env
|
env
|
||||||
});
|
});
|
||||||
if (output.status !== 0) {
|
const stderr = output.stderr.toString().trim();
|
||||||
console.log(output.stderr.toString());
|
if (output.status !== 9) {
|
||||||
|
console.log(stderr);
|
||||||
}
|
}
|
||||||
assert.strictEqual(output.status, 0);
|
assert.strictEqual(output.status, 9);
|
||||||
const profiles = getCpuProfiles(tmpdir.path);
|
assert.strictEqual(
|
||||||
assert.deepStrictEqual(profiles, [file]);
|
stderr,
|
||||||
verifyFrames(output, file, 'fibonacci.js');
|
`${process.execPath}: --cpu-prof-name must be used with --cpu-prof`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output to specified --cpu-prof-path with --cpu-prof
|
// --cpu-prof-dir without --cpu-prof
|
||||||
{
|
{
|
||||||
tmpdir.refresh();
|
tmpdir.refresh();
|
||||||
const file = path.join(tmpdir.path, 'test.cpuprofile');
|
|
||||||
const output = spawnSync(process.execPath, [
|
const output = spawnSync(process.execPath, [
|
||||||
'--cpu-prof',
|
'--cpu-prof-dir',
|
||||||
'--cpu-prof-path',
|
'prof',
|
||||||
file,
|
|
||||||
fixtures.path('workload', 'fibonacci.js'),
|
fixtures.path('workload', 'fibonacci.js'),
|
||||||
], {
|
], {
|
||||||
cwd: tmpdir.path,
|
cwd: tmpdir.path,
|
||||||
env
|
env
|
||||||
});
|
});
|
||||||
if (output.status !== 0) {
|
const stderr = output.stderr.toString().trim();
|
||||||
console.log(output.stderr.toString());
|
if (output.status !== 9) {
|
||||||
|
console.log(stderr);
|
||||||
}
|
}
|
||||||
assert.strictEqual(output.status, 0);
|
assert.strictEqual(output.status, 9);
|
||||||
const profiles = getCpuProfiles(tmpdir.path);
|
assert.strictEqual(
|
||||||
assert.deepStrictEqual(profiles, [file]);
|
stderr,
|
||||||
verifyFrames(output, file, 'fibonacci.js');
|
`${process.execPath}: --cpu-prof-dir must be used with --cpu-prof`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output to specified --cpu-prof-path when it's not absolute
|
// --cpu-prof-name
|
||||||
{
|
{
|
||||||
tmpdir.refresh();
|
tmpdir.refresh();
|
||||||
const file = path.join(tmpdir.path, 'test.cpuprofile');
|
const file = path.join(tmpdir.path, 'test.cpuprofile');
|
||||||
const output = spawnSync(process.execPath, [
|
const output = spawnSync(process.execPath, [
|
||||||
'--cpu-prof',
|
'--cpu-prof',
|
||||||
'--cpu-prof-path',
|
'--cpu-prof-name',
|
||||||
'test.cpuprofile',
|
'test.cpuprofile',
|
||||||
fixtures.path('workload', 'fibonacci.js'),
|
fixtures.path('workload', 'fibonacci.js'),
|
||||||
], {
|
], {
|
||||||
@ -200,3 +204,108 @@ const env = {
|
|||||||
assert.deepStrictEqual(profiles, [file]);
|
assert.deepStrictEqual(profiles, [file]);
|
||||||
verifyFrames(output, file, 'fibonacci.js');
|
verifyFrames(output, file, 'fibonacci.js');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// relative --cpu-prof-dir
|
||||||
|
{
|
||||||
|
tmpdir.refresh();
|
||||||
|
const output = spawnSync(process.execPath, [
|
||||||
|
'--cpu-prof',
|
||||||
|
'--cpu-prof-dir',
|
||||||
|
'prof',
|
||||||
|
fixtures.path('workload', 'fibonacci.js'),
|
||||||
|
], {
|
||||||
|
cwd: tmpdir.path,
|
||||||
|
env
|
||||||
|
});
|
||||||
|
if (output.status !== 0) {
|
||||||
|
console.log(output.stderr.toString());
|
||||||
|
}
|
||||||
|
assert.strictEqual(output.status, 0);
|
||||||
|
const dir = path.join(tmpdir.path, 'prof');
|
||||||
|
assert(fs.existsSync(dir));
|
||||||
|
const profiles = getCpuProfiles(dir);
|
||||||
|
assert.strictEqual(profiles.length, 1);
|
||||||
|
verifyFrames(output, profiles[0], 'fibonacci.js');
|
||||||
|
}
|
||||||
|
|
||||||
|
// absolute --cpu-prof-dir
|
||||||
|
{
|
||||||
|
tmpdir.refresh();
|
||||||
|
const dir = path.join(tmpdir.path, 'prof');
|
||||||
|
const output = spawnSync(process.execPath, [
|
||||||
|
'--cpu-prof',
|
||||||
|
'--cpu-prof-dir',
|
||||||
|
dir,
|
||||||
|
fixtures.path('workload', 'fibonacci.js'),
|
||||||
|
], {
|
||||||
|
cwd: tmpdir.path,
|
||||||
|
env
|
||||||
|
});
|
||||||
|
if (output.status !== 0) {
|
||||||
|
console.log(output.stderr.toString());
|
||||||
|
}
|
||||||
|
assert.strictEqual(output.status, 0);
|
||||||
|
assert(fs.existsSync(dir));
|
||||||
|
const profiles = getCpuProfiles(dir);
|
||||||
|
assert.strictEqual(profiles.length, 1);
|
||||||
|
verifyFrames(output, profiles[0], 'fibonacci.js');
|
||||||
|
}
|
||||||
|
|
||||||
|
// --cpu-prof-dir and --cpu-prof-name
|
||||||
|
{
|
||||||
|
tmpdir.refresh();
|
||||||
|
const dir = path.join(tmpdir.path, 'prof');
|
||||||
|
const file = path.join(dir, 'test.cpuprofile');
|
||||||
|
const output = spawnSync(process.execPath, [
|
||||||
|
'--cpu-prof',
|
||||||
|
'--cpu-prof-name',
|
||||||
|
'test.cpuprofile',
|
||||||
|
'--cpu-prof-dir',
|
||||||
|
dir,
|
||||||
|
fixtures.path('workload', 'fibonacci.js'),
|
||||||
|
], {
|
||||||
|
cwd: tmpdir.path,
|
||||||
|
env
|
||||||
|
});
|
||||||
|
if (output.status !== 0) {
|
||||||
|
console.log(output.stderr.toString());
|
||||||
|
}
|
||||||
|
assert.strictEqual(output.status, 0);
|
||||||
|
assert(fs.existsSync(dir));
|
||||||
|
const profiles = getCpuProfiles(dir);
|
||||||
|
assert.deepStrictEqual(profiles, [file]);
|
||||||
|
verifyFrames(output, file, 'fibonacci.js');
|
||||||
|
}
|
||||||
|
|
||||||
|
// --cpu-prof-dir with worker
|
||||||
|
{
|
||||||
|
tmpdir.refresh();
|
||||||
|
const output = spawnSync(process.execPath, [
|
||||||
|
'--cpu-prof-dir',
|
||||||
|
'prof',
|
||||||
|
'--cpu-prof',
|
||||||
|
fixtures.path('workload', 'fibonacci-worker.js'),
|
||||||
|
], {
|
||||||
|
cwd: tmpdir.path,
|
||||||
|
env
|
||||||
|
});
|
||||||
|
if (output.status !== 0) {
|
||||||
|
console.log(output.stderr.toString());
|
||||||
|
}
|
||||||
|
assert.strictEqual(output.status, 0);
|
||||||
|
const dir = path.join(tmpdir.path, 'prof');
|
||||||
|
assert(fs.existsSync(dir));
|
||||||
|
const profiles = getCpuProfiles(dir);
|
||||||
|
assert.strictEqual(profiles.length, 2);
|
||||||
|
const profile1 = getFrames(output, profiles[0], 'fibonacci.js');
|
||||||
|
const profile2 = getFrames(output, profiles[1], 'fibonacci.js');
|
||||||
|
if (profile1.frames.length === 0 && profile2.frames.length === 0) {
|
||||||
|
// Show native debug output and the profile for debugging.
|
||||||
|
console.log(output.stderr.toString());
|
||||||
|
console.log('CPU path: ', profiles[0]);
|
||||||
|
console.log(profile1.nodes);
|
||||||
|
console.log('CPU path: ', profiles[1]);
|
||||||
|
console.log(profile2.nodes);
|
||||||
|
}
|
||||||
|
assert(profile1.frames.length > 0 || profile2.frames.length > 0);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user