Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/nodejs/node into fork
Browse files Browse the repository at this point in the history
  • Loading branch information
Etienne Pierre-Doray committed Nov 18, 2023
2 parents db9e2b4 + 4e23d69 commit 7249d66
Show file tree
Hide file tree
Showing 12 changed files with 215 additions and 40 deletions.
32 changes: 32 additions & 0 deletions benchmark/esm/import-meta.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';

const path = require('path');
const { pathToFileURL, fileURLToPath } = require('url');
const common = require('../common');
const assert = require('assert');
const bench = common.createBenchmark(main, {
n: [1000],
});

const file = pathToFileURL(
path.resolve(__filename, '../../fixtures/esm-dir-file.mjs'),
);
async function load(array, n) {
for (let i = 0; i < n; i++) {
array[i] = await import(`${file}?i=${i}`);
}
return array;
}

function main({ n }) {
const array = [];
for (let i = 0; i < n; ++i) {
array.push({ dirname: '', filename: '', i: 0 });
}

bench.start();
load(array, n).then((arr) => {
bench.end(n);
assert.strictEqual(arr[n - 1].filename, fileURLToPath(file));
});
}
5 changes: 2 additions & 3 deletions benchmark/fixtures/esm-dir-file.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
import assert from 'assert';
assert.ok(import.meta.dirname);
assert.ok(import.meta.filename);
export const dirname = import.meta.dirname;
export const filename = import.meta.filename;
5 changes: 0 additions & 5 deletions benchmark/fixtures/load-esm-dir-file.js

This file was deleted.

1 change: 0 additions & 1 deletion benchmark/misc/startup.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const bench = common.createBenchmark(main, {
script: [
'benchmark/fixtures/require-builtins',
'test/fixtures/semicolon',
'benchmark/fixtures/load-esm-dir-file',
],
mode: ['process', 'worker'],
count: [30],
Expand Down
23 changes: 23 additions & 0 deletions benchmark/perf_hooks/now.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use strict';

const assert = require('assert');
const common = require('../common.js');

const bench = common.createBenchmark(main, {
n: [1e6],
});

function main({ n }) {
const arr = [];
for (let i = 0; i < n; ++i) {
arr.push(performance.now());
}

bench.start();
for (let i = 0; i < n; i++) {
arr[i] = performance.now();
}
bench.end(n);

assert.strictEqual(arr.length, n);
}
18 changes: 18 additions & 0 deletions deps/base64/unofficial.gni
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ template("base64_gn_build") {
"HAVE_SSE42=1",
"HAVE_AVX=1",
"HAVE_AVX2=1",
"HAVE_AVX512=1",
]
}
if (target_cpu == "arm") {
Expand Down Expand Up @@ -65,6 +66,7 @@ template("base64_gn_build") {
":base64_sse42",
":base64_avx",
":base64_avx2",
":base64_avx512",
":base64_neon32",
":base64_neon64",
]
Expand Down Expand Up @@ -111,6 +113,7 @@ template("base64_gn_build") {
}
}
}

source_set("base64_avx2") {
configs += [ ":base64_internal_config" ]
sources = [ "base64/lib/arch/avx2/codec.c" ]
Expand All @@ -123,6 +126,21 @@ template("base64_gn_build") {
}
}

source_set("base64_avx512") {
configs += [ ":base64_internal_config" ]
sources = [ "base64/lib/arch/avx512/codec.c" ]
if (target_cpu == "x86" || target_cpu == "x64") {
if (is_clang || !is_win) {
cflags_c = [
"-mavx512vl",
"-mavx512vbmi",
]
} else if (is_win) {
cflags_c = [ "/arch:AVX512" ]
}
}
}

source_set("base64_neon32") {
configs += [ ":base64_internal_config" ]
sources = [ "base64/lib/arch/neon32/codec.c" ]
Expand Down
7 changes: 1 addition & 6 deletions lib/internal/perf/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const {
NODE_PERFORMANCE_MILESTONE_TIME_ORIGIN,
},
milestones,
now,
} = internalBinding('performance');

function getTimeOrigin() {
Expand All @@ -13,12 +14,6 @@ function getTimeOrigin() {
return milestones[NODE_PERFORMANCE_MILESTONE_TIME_ORIGIN] / 1e6;
}

// Returns the time relative to the process start time in milliseconds.
function now() {
const hr = process.hrtime();
return (hr[0] * 1000 + hr[1] / 1e6) - getTimeOrigin();
}

// Returns the milestone relative to the process start time in milliseconds.
function getMilestoneTimestamp(milestoneIdx) {
const ns = milestones[milestoneIdx];
Expand Down
3 changes: 3 additions & 0 deletions src/node_external_reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ using CFunctionCallbackWithOneByteString =
using CFunctionCallback = void (*)(v8::Local<v8::Value> receiver);
using CFunctionCallbackReturnDouble =
double (*)(v8::Local<v8::Object> receiver);
using CFunctionCallbackValueReturnDouble =
double (*)(v8::Local<v8::Value> receiver);
using CFunctionCallbackWithInt64 = void (*)(v8::Local<v8::Object> receiver,
int64_t);
using CFunctionCallbackWithBool = void (*)(v8::Local<v8::Object> receiver,
Expand All @@ -38,6 +40,7 @@ class ExternalReferenceRegistry {
V(CFunctionCallback) \
V(CFunctionCallbackWithOneByteString) \
V(CFunctionCallbackReturnDouble) \
V(CFunctionCallbackValueReturnDouble) \
V(CFunctionCallbackWithInt64) \
V(CFunctionCallbackWithBool) \
V(CFunctionCallbackWithString) \
Expand Down
21 changes: 21 additions & 0 deletions src/node_perf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,22 @@ void MarkBootstrapComplete(const FunctionCallbackInfo<Value>& args) {
performance::NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE);
}

static double PerformanceNowImpl() {
return static_cast<double>(uv_hrtime() - performance_process_start) /
NANOS_PER_MILLIS;
}

static double FastPerformanceNow(v8::Local<v8::Value> receiver) {
return PerformanceNowImpl();
}

static void SlowPerformanceNow(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(PerformanceNowImpl());
}

static v8::CFunction fast_performance_now(
v8::CFunction::Make(FastPerformanceNow));

static void CreatePerIsolateProperties(IsolateData* isolate_data,
Local<ObjectTemplate> target) {
Isolate* isolate = isolate_data->isolate();
Expand All @@ -311,6 +327,8 @@ static void CreatePerIsolateProperties(IsolateData* isolate_data,
SetMethod(isolate, target, "getTimeOriginTimestamp", GetTimeOriginTimeStamp);
SetMethod(isolate, target, "createELDHistogram", CreateELDHistogram);
SetMethod(isolate, target, "markBootstrapComplete", MarkBootstrapComplete);
SetFastMethodNoSideEffect(
isolate, target, "now", SlowPerformanceNow, &fast_performance_now);
}

void CreatePerContextProperties(Local<Object> target,
Expand Down Expand Up @@ -376,6 +394,9 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
registry->Register(GetTimeOriginTimeStamp);
registry->Register(CreateELDHistogram);
registry->Register(MarkBootstrapComplete);
registry->Register(SlowPerformanceNow);
registry->Register(FastPerformanceNow);
registry->Register(fast_performance_now.GetTypeInfo());
HistogramBase::RegisterExternalReferences(registry);
IntervalHistogram::RegisterExternalReferences(registry);
}
Expand Down
128 changes: 103 additions & 25 deletions test/parallel/test-bootstrap-modules.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
// Flags: --expose-internals
'use strict';

// This list must be computed before we require any modules to
// This list must be computed before we require any builtins to
// to eliminate the noise.
const actualModules = new Set(process.moduleLoadList.slice());
const list = process.moduleLoadList.slice();

const common = require('../common');
const assert = require('assert');
const { inspect } = require('util');

const expectedModules = new Set([
const preExecIndex =
list.findIndex((i) => i.includes('pre_execution'));
const actual = {
beforePreExec: new Set(list.slice(0, preExecIndex)),
atRunTime: new Set(list.slice(preExecIndex)),
};

// Currently, we don't add additional builtins to worker snapshots.
// So for worker snapshots we'll just concatenate the two. Once we
// add more builtins to worker snapshots, we should also distinguish
// the two stages for them.
const expected = {};

expected.beforePreExec = new Set([
'Internal Binding builtins',
'Internal Binding encoding_binding',
'Internal Binding modules',
Expand Down Expand Up @@ -85,22 +98,25 @@ const expectedModules = new Set([
'NativeModule internal/modules/package_json_reader',
'Internal Binding module_wrap',
'NativeModule internal/modules/cjs/loader',
'NativeModule internal/vm/module',
'NativeModule internal/modules/esm/utils',
]);

expected.atRunTime = new Set([
'Internal Binding wasm_web_api',
'Internal Binding worker',
'NativeModule internal/modules/run_main',
'NativeModule internal/net',
'NativeModule internal/dns/utils',
'NativeModule internal/process/pre_execution',
'NativeModule internal/vm/module',
'NativeModule internal/modules/esm/utils',
]);

if (common.isMainThread) {
[
'NativeModule internal/idna',
'NativeModule url',
].forEach(expectedModules.add.bind(expectedModules));
} else {
].forEach(expected.beforePreExec.add.bind(expected.beforePreExec));
} else { // Worker.
[
'NativeModule diagnostics_channel',
'NativeModule internal/abort_controller',
Expand Down Expand Up @@ -128,35 +144,97 @@ if (common.isMainThread) {
'NativeModule stream/promises',
'NativeModule string_decoder',
'NativeModule worker_threads',
].forEach(expectedModules.add.bind(expectedModules));
].forEach(expected.atRunTime.add.bind(expected.atRunTime));
// For now we'll concatenate the two stages for workers. We prefer
// atRunTime here because that's what currently happens for these.
}

if (common.isWindows) {
// On Windows fs needs SideEffectFreeRegExpPrototypeExec which uses vm.
expectedModules.add('NativeModule vm');
expected.atRunTime.add('NativeModule vm');
}

if (common.hasIntl) {
expectedModules.add('Internal Binding icu');
expected.beforePreExec.add('Internal Binding icu');
}

if (process.features.inspector) {
expectedModules.add('Internal Binding inspector');
expectedModules.add('NativeModule internal/inspector_async_hook');
expectedModules.add('NativeModule internal/util/inspector');
expected.beforePreExec.add('Internal Binding inspector');
expected.beforePreExec.add('NativeModule internal/util/inspector');
expected.atRunTime.add('NativeModule internal/inspector_async_hook');
}

const difference = (setA, setB) => {
return new Set([...setA].filter((x) => !setB.has(x)));
};
const missingModules = difference(expectedModules, actualModules);
const extraModules = difference(actualModules, expectedModules);
const printSet = (s) => { return `${[...s].sort().join(',\n ')}\n`; };

assert.deepStrictEqual(actualModules, expectedModules,
(missingModules.size > 0 ?
'These modules were not loaded:\n ' +
printSet(missingModules) : '') +
(extraModules.size > 0 ?
'These modules were unexpectedly loaded:\n ' +
printSet(extraModules) : ''));

// Accumulate all the errors and print them at the end instead of throwing
// immediately which makes it harder to update the test.
const errorLogs = [];
function err(message) {
if (typeof message === 'string') {
errorLogs.push(message);
} else {
// Show the items in individual lines for easier copy-pasting.
errorLogs.push(inspect(message, { compact: false }));
}
}

if (common.isMainThread) {
const missing = difference(expected.beforePreExec, actual.beforePreExec);
const extra = difference(actual.beforePreExec, expected.beforePreExec);
if (missing.size !== 0) {
err('These builtins are now no longer loaded before pre-execution.');
err('If this is intentional, remove them from `expected.beforePreExec`.');
err('\n--- These could be removed from expected.beforePreExec ---');
err([...missing].sort());
err('');
}
if (extra.size !== 0) {
err('These builtins are now unexpectedly loaded before pre-execution.');
err('If this is intentional, add them to `expected.beforePreExec`.');
err('\n# Note: loading more builtins before pre-execution can lead to ' +
'startup performance regression or invalid snapshots.');
err('- Consider lazy loading builtins that are not used universally.');
err('- Make sure that the builtins do not access environment dependent ' +
'states e.g. command line arguments or environment variables ' +
'during loading.');
err('- When in doubt, ask @nodejs/startup.');
err('\n--- These could be added to expected.beforePreExec ---');
err([...extra].sort());
err('');
}
}

if (!common.isMainThread) {
// For workers, just merge beforePreExec into atRunTime for now.
// When we start adding modules to the worker snapshot, this branch
// can be removed and we can just remove the common.isMainThread
// conditions.
expected.beforePreExec.forEach(expected.atRunTime.add.bind(expected.atRunTime));
actual.beforePreExec.forEach(actual.atRunTime.add.bind(actual.atRunTime));
}

{
const missing = difference(expected.atRunTime, actual.atRunTime);
const extra = difference(actual.atRunTime, expected.atRunTime);
if (missing.size !== 0) {
err('These builtins are now no longer loaded at run time.');
err('If this is intentional, remove them from `expected.atRunTime`.');
err('\n--- These could be removed from expected.atRunTime ---');
err([...missing].sort());
err('');
}
if (extra.size !== 0) {
err('These builtins are now unexpectedly loaded at run time.');
err('If this is intentional, add them to `expected.atRunTime`.');
err('\n# Note: loading more builtins at run time can lead to ' +
'startup performance regression.');
err('- Consider lazy loading builtins that are not used universally.');
err('\n--- These could be added to expected.atRunTime ---');
err([...extra].sort());
err('');
}
}

assert.strictEqual(errorLogs.length, 0, errorLogs.join('\n'));
4 changes: 4 additions & 0 deletions test/parallel/test-macos-app-sandbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ const nodeBinary = process.execPath;

tmpdir.refresh();

if (!tmpdir.hasEnoughSpace(120 * 1024 * 1024)) {
common.skip('Available disk space < 120MB');
}

const appBundlePath = tmpdir.resolve('node_sandboxed.app');
const appBundleContentPath = path.join(appBundlePath, 'Contents');
const appExecutablePath = path.join(
Expand Down
Loading

0 comments on commit 7249d66

Please sign in to comment.