Skip to content

Commit

Permalink
fs: add fast api to copyFileSync
Browse files Browse the repository at this point in the history
  • Loading branch information
anonrig committed Sep 10, 2023
1 parent 8a748c4 commit 6de6974
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 10 deletions.
23 changes: 23 additions & 0 deletions benchmark/fs/bench-copyFileSync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use strict';

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


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

function main({ n }) {
tmpdir.refresh();
bench.start();
for (let i = 0; i < n; i++) {
try {
fs.copyFileSync(__filename, tmpdir.resolve(`copy-file-bench-${process.pid}`));
} catch {
// do nothing
}
}
bench.end(n);
}
61 changes: 61 additions & 0 deletions fs.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"binary","filename","configuration","rate","time"
"old","fs/bench-copyFileSync.js","n=10000",13616.3012604911,0.734413833
"new","fs/bench-copyFileSync.js","n=10000",13694.96485786424,0.730195375
"old","fs/bench-copyFileSync.js","n=10000",13739.399773134755,0.727833833
"new","fs/bench-copyFileSync.js","n=10000",13699.708435407236,0.729942542
"old","fs/bench-copyFileSync.js","n=10000",13617.464767870439,0.734351083
"new","fs/bench-copyFileSync.js","n=10000",13770.125553154377,0.726209791
"old","fs/bench-copyFileSync.js","n=10000",13556.822063999047,0.737636000
"new","fs/bench-copyFileSync.js","n=10000",13151.13027994143,0.760390916
"old","fs/bench-copyFileSync.js","n=10000",13591.630953240541,0.735746875
"new","fs/bench-copyFileSync.js","n=10000",13373.484259825611,0.747748291
"old","fs/bench-copyFileSync.js","n=10000",13061.165498109005,0.765628458
"new","fs/bench-copyFileSync.js","n=10000",13400.680687575525,0.746230750
"old","fs/bench-copyFileSync.js","n=10000",13461.548606886345,0.742856583
"new","fs/bench-copyFileSync.js","n=10000",12885.627912724512,0.776058417
"old","fs/bench-copyFileSync.js","n=10000",13369.552198935173,0.747968208
"new","fs/bench-copyFileSync.js","n=10000",13449.725771725527,0.743509583
"old","fs/bench-copyFileSync.js","n=10000",13022.627912503243,0.767894166
"new","fs/bench-copyFileSync.js","n=10000",12588.888045587253,0.794351333
"old","fs/bench-copyFileSync.js","n=10000",13382.409609186761,0.747249583
"new","fs/bench-copyFileSync.js","n=10000",13395.875712079207,0.746498416
"old","fs/bench-copyFileSync.js","n=10000",12979.300568621471,0.770457541
"new","fs/bench-copyFileSync.js","n=10000",13537.097497199007,0.738710791
"old","fs/bench-copyFileSync.js","n=10000",13445.54009431686,0.743741042
"new","fs/bench-copyFileSync.js","n=10000",13254.133980293414,0.754481584
"old","fs/bench-copyFileSync.js","n=10000",13477.873044940337,0.741956833
"new","fs/bench-copyFileSync.js","n=10000",12765.20104074684,0.783379750
"old","fs/bench-copyFileSync.js","n=10000",13311.925538413308,0.751206125
"new","fs/bench-copyFileSync.js","n=10000",12993.160844497557,0.769635666
"old","fs/bench-copyFileSync.js","n=10000",13785.116009808622,0.725420083
"new","fs/bench-copyFileSync.js","n=10000",13453.389135749238,0.743307125
"old","fs/bench-copyFileSync.js","n=10000",13576.532014056462,0.736565125
"new","fs/bench-copyFileSync.js","n=10000",13593.95129307099,0.735621291
"old","fs/bench-copyFileSync.js","n=10000",13077.568781881682,0.764668125
"new","fs/bench-copyFileSync.js","n=10000",13635.626072953326,0.733373000
"old","fs/bench-copyFileSync.js","n=10000",13455.474669075922,0.743191916
"new","fs/bench-copyFileSync.js","n=10000",13276.039117307597,0.753236708
"old","fs/bench-copyFileSync.js","n=10000",13296.166116981,0.752096500
"new","fs/bench-copyFileSync.js","n=10000",13418.647591833682,0.745231584
"old","fs/bench-copyFileSync.js","n=10000",12954.297782798225,0.771944583
"new","fs/bench-copyFileSync.js","n=10000",12721.505259388312,0.786070500
"old","fs/bench-copyFileSync.js","n=10000",13728.349814036528,0.728419667
"new","fs/bench-copyFileSync.js","n=10000",13828.01919674765,0.723169375
"old","fs/bench-copyFileSync.js","n=10000",13411.63118725588,0.745621458
"new","fs/bench-copyFileSync.js","n=10000",13463.148004183964,0.742768333
"old","fs/bench-copyFileSync.js","n=10000",12420.184155039242,0.805141041
"new","fs/bench-copyFileSync.js","n=10000",13677.715411194868,0.731116250
"old","fs/bench-copyFileSync.js","n=10000",13569.371040912953,0.736953833
"new","fs/bench-copyFileSync.js","n=10000",13635.334019896036,0.733388708
"old","fs/bench-copyFileSync.js","n=10000",13605.901112245407,0.734975208
"new","fs/bench-copyFileSync.js","n=10000",13630.905858832957,0.733626958
"old","fs/bench-copyFileSync.js","n=10000",13355.137821683535,0.748775500
"new","fs/bench-copyFileSync.js","n=10000",13303.936812643457,0.751657208
"old","fs/bench-copyFileSync.js","n=10000",13505.185303742704,0.740456334
"new","fs/bench-copyFileSync.js","n=10000",13190.559439048982,0.758117959
"old","fs/bench-copyFileSync.js","n=10000",13659.444222785054,0.732094208
"new","fs/bench-copyFileSync.js","n=10000",13615.53032156341,0.734455417
"old","fs/bench-copyFileSync.js","n=10000",13565.95095535666,0.737139625
"new","fs/bench-copyFileSync.js","n=10000",12739.006987933875,0.784990542
"old","fs/bench-copyFileSync.js","n=10000",13675.54329087248,0.731232375
"new","fs/bench-copyFileSync.js","n=10000",13476.086251690203,0.742055209
11 changes: 1 addition & 10 deletions lib/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2977,16 +2977,7 @@ function copyFile(src, dest, mode, callback) {
* @returns {void}
*/
function copyFileSync(src, dest, mode) {
src = getValidatedPath(src, 'src');
dest = getValidatedPath(dest, 'dest');

const ctx = { path: src, dest }; // non-prefixed

src = pathModule._makeLong(src);
dest = pathModule._makeLong(dest);
mode = getValidMode(mode, 'copyFile');
binding.copyFile(src, dest, mode, undefined, ctx);
handleErrorFromBinding(ctx);
syncFs.copyFile(src, dest, mode);
}

/**
Expand Down
16 changes: 16 additions & 0 deletions lib/internal/fs/sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,24 @@ function access(path, mode) {
}
}

function copyFile(src, dest, mode) {
src = getValidatedPath(src, 'src');
dest = getValidatedPath(dest, 'dest');

const errno = syncBinding.copyFile(
pathModule.toNamespacedPath(src),
pathModule.toNamespacedPath(dest),
getValidMode(mode, 'copyFile'),
);

if (errno < 0) {
handleErrorFromBinding({ errno, syscall: 'copyfile', path: src, dest });
}
}

module.exports = {
readFileUtf8,
exists,
access,
copyFile,
};
Binary file added node-main
Binary file not shown.
6 changes: 6 additions & 0 deletions src/node_external_reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ using CFunctionCallbackWithStrings =
bool (*)(v8::Local<v8::Value>,
const v8::FastOneByteString& input,
const v8::FastOneByteString& base);
using CFunctionCallbackWithStringsReturningInt =
int32_t (*)(v8::Local<v8::Value>,
const v8::FastOneByteString& input,
const v8::FastOneByteString& base,
int32_t flags);
using CFunctionWithUint32 = uint32_t (*)(v8::Local<v8::Value>,
const uint32_t input);

Expand All @@ -42,6 +47,7 @@ class ExternalReferenceRegistry {
V(CFunctionCallbackWithBool) \
V(CFunctionCallbackWithString) \
V(CFunctionCallbackWithStrings) \
V(CFunctionCallbackWithStringsReturningInt) \
V(CFunctionWithUint32) \
V(const v8::CFunctionInfo*) \
V(v8::FunctionCallback) \
Expand Down
53 changes: 53 additions & 0 deletions src/node_file_sync.cc
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,54 @@ void BindingData::Deserialize(v8::Local<v8::Context> context,
CHECK_NOT_NULL(binding);
}

inline int32_t BindingData::CopyFileInternal(const std::string_view src,
const std::string_view dest,
int flags) {
uv_fs_t req;
auto make = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); });
FS_SYNC_TRACE_BEGIN(copyfile);
uv_fs_copyfile(nullptr, &req, src.data(), dest.data(), flags, nullptr);
FS_SYNC_TRACE_END(copyfile);

return int32_t(req.result);
}

void BindingData::CopyFile(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
Isolate* isolate = env->isolate();

const int argc = args.Length();
CHECK_GE(argc, 3);

BufferValue src(isolate, args[0]);
CHECK_NOT_NULL(*src);
THROW_IF_INSUFFICIENT_PERMISSIONS(
env, permission::PermissionScope::kFileSystemRead, src.ToStringView());

BufferValue dest(isolate, args[1]);
CHECK_NOT_NULL(*dest);
THROW_IF_INSUFFICIENT_PERMISSIONS(
env, permission::PermissionScope::kFileSystemWrite, dest.ToStringView());

CHECK(args[2]->IsInt32());
const int flags = args[2].As<Int32>()->Value();

return args.GetReturnValue().Set(
CopyFileInternal(src.ToStringView(), dest.ToStringView(), flags));
}

int32_t BindingData::FastCopyFile(Local<Value> receiver,
const FastOneByteString& src,
const FastOneByteString& dest,
int32_t flags) {
// TODO(@anonrig): Add "THROW_IF_INSUFFICIENT_PERMISSIONS"
return CopyFileInternal(std::string_view(src.data, src.length),
std::string_view(dest.data, dest.length),
flags);
}

CFunction BindingData::fast_copy_file_(CFunction::Make(FastCopyFile));

void BindingData::Access(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
Isolate* isolate = env->isolate();
Expand Down Expand Up @@ -264,6 +312,8 @@ void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
Local<ObjectTemplate> target) {
Isolate* isolate = isolate_data->isolate();
SetMethodNoSideEffect(isolate, target, "access", Access);
SetFastMethodNoSideEffect(
isolate, target, "copyFile", CopyFile, &fast_copy_file_);
SetFastMethodNoSideEffect(isolate, target, "exists", Exists, &fast_exists_);
SetMethodNoSideEffect(isolate, target, "readFileUtf8", ReadFileUtf8);
}
Expand All @@ -279,6 +329,9 @@ void BindingData::CreatePerContextProperties(Local<Object> target,
void BindingData::RegisterExternalReferences(
ExternalReferenceRegistry* registry) {
registry->Register(Access);
registry->Register(CopyFile);
registry->Register(FastCopyFile);
registry->Register(fast_copy_file_.GetTypeInfo());
registry->Register(Exists);
registry->Register(FastExists);
registry->Register(fast_exists_.GetTypeInfo());
Expand Down
10 changes: 10 additions & 0 deletions src/node_file_sync.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ class BindingData : public SnapshotableObject {
SET_SELF_SIZE(BindingData)
SET_MEMORY_INFO_NAME(BindingData)

static void CopyFile(const v8::FunctionCallbackInfo<v8::Value>& args);
static int32_t FastCopyFile(v8::Local<v8::Value> receiver,
const v8::FastOneByteString& src,
const v8::FastOneByteString& dest,
int32_t flags);

static void Exists(const v8::FunctionCallbackInfo<v8::Value>& args);
static bool FastExists(v8::Local<v8::Value> receiver,
const v8::FastOneByteString& path);
Expand All @@ -47,8 +53,12 @@ class BindingData : public SnapshotableObject {
static void RegisterExternalReferences(ExternalReferenceRegistry* registry);

private:
static v8::CFunction fast_copy_file_;
static v8::CFunction fast_exists_;

static int CopyFileInternal(const std::string_view src,
const std::string_view dest,
int flags);
static bool ExistsInternal(const std::string_view path);
};

Expand Down
2 changes: 2 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const fs = require('node:fs')
fs.copyFileSync(__filename, './test.txt')

0 comments on commit 6de6974

Please sign in to comment.