GeezerVison is showing github.com — fs: improve error performance of `opendirSync` · nodejs/node@b618fe2
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboard +43Lines changed: 43 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const common = require('../common'); | | 4 | +const fs = require('fs'); | | 5 | +const path = require('path'); | | 6 | +const tmpdir = require('../../test/common/tmpdir'); | | 7 | +tmpdir.refresh(); | | 8 | + | | 9 | +const testFiles = fs.readdirSync('test', { withFileTypes: true }) | | 10 | + .filter((f) => f.isDirectory()) | | 11 | + .map((f) => path.join(f.path, f.name)); | | 12 | +const bench = common.createBenchmark(main, { | | 13 | + type: ['existing', 'non-existing'], | | 14 | + n: [1e3], | | 15 | +}); | | 16 | + | | 17 | +function main({ n, type }) { | | 18 | + let files; | | 19 | + | | 20 | + switch (type) { | | 21 | + case 'existing': | | 22 | + files = testFiles; | | 23 | + break; | | 24 | + case 'non-existing': | | 25 | + files = [tmpdir.resolve(`.non-existing-file-${Date.now()}`)]; | | 26 | + break; | | 27 | + default: | | 28 | + new Error('Invalid type'); | | 29 | + } | | 30 | + | | 31 | + bench.start(); | | 32 | + for (let i = 0; i < n; i++) { | | 33 | + for (let j = 0; j < files.length; j++) { | | 34 | + try { | | 35 | + const dir = fs.opendirSync(files[j]); | | 36 | + dir.closeSync(); | | 37 | + } catch { | | 38 | + // do nothing | | 39 | + } | | 40 | + } | | 41 | + } | | 42 | + bench.end(n); | | 43 | +} |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/fs/dir.js +2-9Lines changed: 2 additions & 9 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -322,18 +322,11 @@ function opendir(path, options, callback) { | 322 | 322 |
| 323 | 323 | function opendirSync(path, options) { | 324 | 324 | path = getValidatedPath(path); | 325 | | - options = getOptions(options, { | 326 | | - encoding: 'utf8', | 327 | | - }); | | 325 | + options = getOptions(options, { encoding: 'utf8' }); | 328 | 326 |
| 329 | | - const ctx = { path }; | 330 | | - const handle = dirBinding.opendir( | | 327 | + const handle = dirBinding.opendirSync( | 331 | 328 | pathModule.toNamespacedPath(path), | 332 | | - options.encoding, | 333 | | - undefined, | 334 | | - ctx, | 335 | 329 | ); | 336 | | - handleErrorFromBinding(ctx); | 337 | 330 |
| 338 | 331 | return new Dir(handle, path, options); | 339 | 332 | } | |
Collapse file Copy file name to clipboardExpand all lines: src/node_dir.cc +28Lines changed: 28 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -397,6 +397,32 @@ static void OpenDir(const FunctionCallbackInfo<Value>& args) { | 397 | 397 | } | 398 | 398 | } | 399 | 399 |
| | 400 | +static void OpenDirSync(const FunctionCallbackInfo<Value>& args) { | | 401 | + Environment* env = Environment::GetCurrent(args); | | 402 | + Isolate* isolate = env->isolate(); | | 403 | + | | 404 | + CHECK_GE(args.Length(), 1); | | 405 | + | | 406 | + BufferValue path(isolate, args[0]); | | 407 | + CHECK_NOT_NULL(*path); | | 408 | + THROW_IF_INSUFFICIENT_PERMISSIONS( | | 409 | + env, permission::PermissionScope::kFileSystemRead, path.ToStringView()); | | 410 | + | | 411 | + uv_fs_t req; | | 412 | + auto make = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); }); | | 413 | + FS_DIR_SYNC_TRACE_BEGIN(opendir); | | 414 | + int err = uv_fs_opendir(nullptr, &req, *path, nullptr); | | 415 | + FS_DIR_SYNC_TRACE_END(opendir); | | 416 | + if (err < 0) { | | 417 | + return env->ThrowUVException(err, "opendir"); | | 418 | + } | | 419 | + | | 420 | + uv_dir_t* dir = static_cast<uv_dir_t*>(req.ptr); | | 421 | + DirHandle* handle = DirHandle::New(env, dir); | | 422 | + | | 423 | + args.GetReturnValue().Set(handle->object().As<Value>()); | | 424 | +} | | 425 | + | 400 | 426 | void Initialize(Local<Object> target, | 401 | 427 | Local<Value> unused, | 402 | 428 | Local<Context> context, | @@ -405,6 +431,7 @@ void Initialize(Local<Object> target, | 405 | 431 | Isolate* isolate = env->isolate(); | 406 | 432 |
| 407 | 433 | SetMethod(context, target, "opendir", OpenDir); | | 434 | + SetMethod(context, target, "opendirSync", OpenDirSync); | 408 | 435 |
| 409 | 436 | // Create FunctionTemplate for DirHandle | 410 | 437 | Local<FunctionTemplate> dir = NewFunctionTemplate(isolate, DirHandle::New); | @@ -419,6 +446,7 @@ void Initialize(Local<Object> target, | 419 | 446 |
| 420 | 447 | void RegisterExternalReferences(ExternalReferenceRegistry* registry) { | 421 | 448 | registry->Register(OpenDir); | | 449 | + registry->Register(OpenDirSync); | 422 | 450 | registry->Register(DirHandle::New); | 423 | 451 | registry->Register(DirHandle::Read); | 424 | 452 | registry->Register(DirHandle::Close); | |
|