Skip to content

Commit

Permalink
Merge branch 'main' into perf-timessync
Browse files Browse the repository at this point in the history
  • Loading branch information
CanadaHonk authored Sep 27, 2023
2 parents ae73a09 + 783f64b commit 4a1c86d
Show file tree
Hide file tree
Showing 25 changed files with 467 additions and 226 deletions.
1 change: 1 addition & 0 deletions .github/workflows/tools.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ on:
- corepack
- doc
- eslint
- github_reporter
- googletest
- histogram
- icu
Expand Down
43 changes: 43 additions & 0 deletions benchmark/fs/bench-unlinkSync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use strict';

const common = require('../common');
const fs = require('fs');
const tmpdir = require('../../test/common/tmpdir');
tmpdir.refresh();

const bench = common.createBenchmark(main, {
type: ['existing', 'non-existing'],
n: [1e3],
});

function main({ n, type }) {
let files;

switch (type) {
case 'existing':
files = [];

// Populate tmpdir with mock files
for (let i = 0; i < n; i++) {
const path = tmpdir.resolve(`unlinksync-bench-file-${i}`);
fs.writeFileSync(path, 'bench');
files.push(path);
}
break;
case 'non-existing':
files = new Array(n).fill(tmpdir.resolve(`.non-existing-file-${Date.now()}`));
break;
default:
new Error('Invalid type');
}

bench.start();
for (let i = 0; i < n; i++) {
try {
fs.unlinkSync(files[i]);
} catch {
// do nothing
}
}
bench.end(n);
}
18 changes: 15 additions & 3 deletions benchmark/fs/readFileSync.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,21 @@ const fs = require('fs');
const bench = common.createBenchmark(main, {
encoding: ['undefined', 'utf8'],
path: ['existing', 'non-existing'],
n: [60e1],
hasFileDescriptor: ['true', 'false'],
n: [1e4],
});

function main({ n, encoding, path }) {
function main({ n, encoding, path, hasFileDescriptor }) {
const enc = encoding === 'undefined' ? undefined : encoding;
const file = path === 'existing' ? __filename : '/tmp/not-found';
let file;
let shouldClose = false;

if (hasFileDescriptor === 'true') {
shouldClose = path === 'existing';
file = path === 'existing' ? fs.openSync(__filename) : -1;
} else {
file = path === 'existing' ? __filename : '/tmp/not-found';
}
bench.start();
for (let i = 0; i < n; ++i) {
try {
Expand All @@ -21,4 +30,7 @@ function main({ n, encoding, path }) {
}
}
bench.end(n);
if (shouldClose) {
fs.closeSync(file);
}
}
36 changes: 36 additions & 0 deletions benchmark/perf_hooks/timerfied.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use strict';

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

const {
PerformanceObserver,
performance,
} = require('perf_hooks');

function randomFn() {
return Math.random();
}

const bench = common.createBenchmark(main, {
n: [1e5],
observe: ['function'],
});

let _result;

function main({ n, observe }) {
const obs = new PerformanceObserver(() => {
bench.end(n);
});
obs.observe({ entryTypes: [observe], buffered: true });

const timerfied = performance.timerify(randomFn);

bench.start();
for (let i = 0; i < n; i++)
_result = timerfied();

// Avoid V8 deadcode (elimination)
assert.ok(_result);
}
23 changes: 23 additions & 0 deletions benchmark/url/whatwg-url-validity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use strict';
const common = require('../common.js');
const url = require('url');
const URL = url.URL;

const bench = common.createBenchmark(main, {
type: ['valid', 'invalid'],
e: [1e5],
});

// This benchmark is used to compare the `Invalid URL` path of the URL parser
function main({ type, e }) {
const url = type === 'valid' ? 'https://www.nodejs.org' : 'www.nodejs.org';
bench.start();
for (let i = 0; i < e; i++) {
try {
new URL(url);
} catch {
// do nothing
}
}
bench.end(e);
}
11 changes: 3 additions & 8 deletions lib/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -437,13 +437,11 @@ function tryReadSync(fd, isUserFd, buffer, pos, len) {
function readFileSync(path, options) {
options = getOptions(options, { flag: 'r' });

const isUserFd = isFd(path); // File descriptor ownership

// TODO(@anonrig): Do not handle file descriptor ownership for now.
if (!isUserFd && (options.encoding === 'utf8' || options.encoding === 'utf-8')) {
if (options.encoding === 'utf8' || options.encoding === 'utf-8') {
return syncFs.readFileUtf8(path, options.flag);
}

const isUserFd = isFd(path); // File descriptor ownership
const fd = isUserFd ? path : fs.openSync(path, options.flag, 0o666);

const stats = tryStatSync(fd, isUserFd);
Expand Down Expand Up @@ -1852,10 +1850,7 @@ function unlink(path, callback) {
* @returns {void}
*/
function unlinkSync(path) {
path = getValidatedPath(path);
const ctx = { path };
binding.unlink(pathModule.toNamespacedPath(path), undefined, ctx);
handleErrorFromBinding(ctx);
return syncFs.unlink(path);
}

/**
Expand Down
7 changes: 6 additions & 1 deletion lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -1370,8 +1370,13 @@ E('ERR_INVALID_SYNC_FORK_INPUT',
E('ERR_INVALID_THIS', 'Value of "this" must be of type %s', TypeError);
E('ERR_INVALID_TUPLE', '%s must be an iterable %s tuple', TypeError);
E('ERR_INVALID_URI', 'URI malformed', URIError);
E('ERR_INVALID_URL', function(input) {
E('ERR_INVALID_URL', function(input, base = null) {
this.input = input;

if (base != null) {
this.base = base;
}

// Don't include URL in message.
// (See https://github.com/nodejs/node/pull/38614)
return 'Invalid URL';
Expand Down
12 changes: 10 additions & 2 deletions lib/internal/fs/sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const {
getValidatedFd,
toUnixTimestamp,
} = require('internal/fs/utils');
const { parseFileMode } = require('internal/validators');
const { parseFileMode, isInt32 } = require('internal/validators');

const binding = internalBinding('fs');

Expand All @@ -20,7 +20,9 @@ const binding = internalBinding('fs');
* @return {string}
*/
function readFileUtf8(path, flag) {
path = pathModule.toNamespacedPath(getValidatedPath(path));
if (!isInt32(path)) {
path = pathModule.toNamespacedPath(getValidatedPath(path));
}
return binding.readFileUtf8(path, stringToFlags(flag));
}

Expand Down Expand Up @@ -104,6 +106,11 @@ function lutimes(path, atime, mtime) {
return binding.lutimesSync(path, toUnixTimestamp(atime), toUnixTimestamp(mtime));
}

function unlink(path) {
path = pathModule.toNamespacedPath(getValidatedPath(path));
return binding.unlinkSync(path);
}

module.exports = {
readFileUtf8,
exists,
Expand All @@ -116,4 +123,5 @@ module.exports = {
utimes,
futimes,
lutimes,
unlink,
};
26 changes: 16 additions & 10 deletions lib/internal/perf/performance_entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

const {
ObjectDefineProperties,
ReflectConstruct,
Symbol,
} = primordials;

Expand All @@ -25,14 +24,17 @@ const kEntryType = Symbol('PerformanceEntry.EntryType');
const kStartTime = Symbol('PerformanceEntry.StartTime');
const kDuration = Symbol('PerformanceEntry.Duration');
const kDetail = Symbol('NodePerformanceEntry.Detail');
const kSkipThrow = Symbol('kSkipThrow');

function isPerformanceEntry(obj) {
return obj?.[kName] !== undefined;
}

class PerformanceEntry {
constructor() {
throw new ERR_ILLEGAL_CONSTRUCTOR();
constructor(skipThrowSymbol = undefined) {
if (skipThrowSymbol !== kSkipThrow) {
throw new ERR_ILLEGAL_CONSTRUCTOR();
}
}

get name() {
Expand Down Expand Up @@ -92,9 +94,11 @@ function initPerformanceEntry(entry, name, type, start, duration) {
}

function createPerformanceEntry(name, type, start, duration) {
return ReflectConstruct(function PerformanceEntry() {
initPerformanceEntry(this, name, type, start, duration);
}, [], PerformanceEntry);
const entry = new PerformanceEntry(kSkipThrow);

initPerformanceEntry(entry, name, type, start, duration);

return entry;
}

/**
Expand All @@ -119,10 +123,12 @@ class PerformanceNodeEntry extends PerformanceEntry {
}

function createPerformanceNodeEntry(name, type, start, duration, detail) {
return ReflectConstruct(function PerformanceNodeEntry() {
initPerformanceEntry(this, name, type, start, duration);
this[kDetail] = detail;
}, [], PerformanceNodeEntry);
const entry = new PerformanceNodeEntry(kSkipThrow);

initPerformanceEntry(entry, name, type, start, duration);
entry[kDetail] = detail;

return entry;
}

module.exports = {
Expand Down
Loading

0 comments on commit 4a1c86d

Please sign in to comment.