From 292263e3780bd6f62b5c4cbf69128d6d11546f4d Mon Sep 17 00:00:00 2001 From: James M Snell Date: Tue, 6 May 2025 21:37:18 -0700 Subject: [PATCH] src: add a couple fast apis in node_os PR-URL: https://github.com/nodejs/node/pull/58210 Reviewed-By: Anna Henningsen Reviewed-By: Matteo Collina Reviewed-By: Yagiz Nizipli --- src/node_external_reference.h | 3 +++ src/node_os.cc | 42 +++++++++++++++++++++++++++++++---- test/parallel/test-os-fast.js | 30 +++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 test/parallel/test-os-fast.js diff --git a/src/node_external_reference.h b/src/node_external_reference.h index 1ade653aeb4..5981e9db9c3 100644 --- a/src/node_external_reference.h +++ b/src/node_external_reference.h @@ -66,6 +66,8 @@ using CFunctionCallbackWithUint8ArrayUint32Int64Bool = v8::FastApiCallbackOptions&); using CFunctionWithUint32 = uint32_t (*)(v8::Local, const uint32_t input); +using CFunctionWithReturnUint32 = uint32_t (*)(v8::Local); +using CFunctionWithReturnDouble = double (*)(v8::Local); using CFunctionWithDoubleReturnDouble = double (*)(v8::Local, v8::Local, const double); @@ -107,6 +109,7 @@ class ExternalReferenceRegistry { V(CFunctionCallbackReturnBool) \ V(CFunctionCallbackReturnDouble) \ V(CFunctionCallbackReturnInt32) \ + V(CFunctionWithReturnUint32) \ V(CFunctionCallbackValueReturnDouble) \ V(CFunctionCallbackValueReturnDoubleUnusedReceiver) \ V(CFunctionCallbackWithInt64) \ diff --git a/src/node_os.cc b/src/node_os.cc index e46d32cd9e5..7f212d345a6 100644 --- a/src/node_os.cc +++ b/src/node_os.cc @@ -20,6 +20,7 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. #include "env-inl.h" +#include "node_debug.h" #include "node_external_reference.h" #include "string_bytes.h" @@ -148,12 +149,26 @@ static void GetFreeMemory(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(amount); } +static double FastGetFreeMemory(Local receiver) { + TRACK_V8_FAST_API_CALL("os.freemem"); + return static_cast(uv_get_free_memory()); +} + +static v8::CFunction fast_get_free_memory( + v8::CFunction::Make(FastGetFreeMemory)); static void GetTotalMemory(const FunctionCallbackInfo& args) { double amount = static_cast(uv_get_total_memory()); args.GetReturnValue().Set(amount); } +double FastGetTotalMemory(Local receiver) { + TRACK_V8_FAST_API_CALL("os.totalmem"); + return static_cast(uv_get_total_memory()); +} + +static v8::CFunction fast_get_total_memory( + v8::CFunction::Make(FastGetTotalMemory)); static void GetUptime(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -398,6 +413,14 @@ static void GetAvailableParallelism(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(parallelism); } +uint32_t FastGetAvailableParallelism(v8::Local receiver) { + TRACK_V8_FAST_API_CALL("os.availableParallelism"); + return uv_available_parallelism(); +} + +static v8::CFunction fast_get_available_parallelism( + v8::CFunction::Make(FastGetAvailableParallelism)); + void Initialize(Local target, Local unused, Local context, @@ -406,16 +429,21 @@ void Initialize(Local target, SetMethod(context, target, "getHostname", GetHostname); SetMethod(context, target, "getLoadAvg", GetLoadAvg); SetMethod(context, target, "getUptime", GetUptime); - SetMethod(context, target, "getTotalMem", GetTotalMemory); - SetMethod(context, target, "getFreeMem", GetFreeMemory); + SetFastMethodNoSideEffect( + context, target, "getTotalMem", GetTotalMemory, &fast_get_total_memory); + SetFastMethodNoSideEffect( + context, target, "getFreeMem", GetFreeMemory, &fast_get_free_memory); SetMethod(context, target, "getCPUs", GetCPUInfo); SetMethod(context, target, "getInterfaceAddresses", GetInterfaceAddresses); SetMethod(context, target, "getHomeDirectory", GetHomeDirectory); SetMethod(context, target, "getUserInfo", GetUserInfo); SetMethod(context, target, "setPriority", SetPriority); SetMethod(context, target, "getPriority", GetPriority); - SetMethod( - context, target, "getAvailableParallelism", GetAvailableParallelism); + SetFastMethodNoSideEffect(context, + target, + "getAvailableParallelism", + GetAvailableParallelism, + &fast_get_available_parallelism); SetMethod(context, target, "getOSInformation", GetOSInformation); target ->Set(context, @@ -429,7 +457,11 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(GetLoadAvg); registry->Register(GetUptime); registry->Register(GetTotalMemory); + registry->Register(FastGetTotalMemory); + registry->Register(fast_get_total_memory.GetTypeInfo()); registry->Register(GetFreeMemory); + registry->Register(FastGetFreeMemory); + registry->Register(fast_get_free_memory.GetTypeInfo()); registry->Register(GetCPUInfo); registry->Register(GetInterfaceAddresses); registry->Register(GetHomeDirectory); @@ -437,6 +469,8 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(SetPriority); registry->Register(GetPriority); registry->Register(GetAvailableParallelism); + registry->Register(FastGetAvailableParallelism); + registry->Register(fast_get_available_parallelism.GetTypeInfo()); registry->Register(GetOSInformation); } diff --git a/test/parallel/test-os-fast.js b/test/parallel/test-os-fast.js new file mode 100644 index 00000000000..786d2f4a7d9 --- /dev/null +++ b/test/parallel/test-os-fast.js @@ -0,0 +1,30 @@ +// Flags: --expose-internals --no-warnings --allow-natives-syntax +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { + totalmem, + freemem, + availableParallelism, +} = require('os'); + +const { internalBinding } = require('internal/test/binding'); + +function testFastOs() { + assert.strictEqual(typeof totalmem(), 'number'); + assert.strictEqual(typeof freemem(), 'number'); + assert.strictEqual(typeof availableParallelism(), 'number'); +} + +eval('%PrepareFunctionForOptimization(testFastOs)'); +testFastOs(); +eval('%OptimizeFunctionOnNextCall(testFastOs)'); +testFastOs(); + +if (common.isDebug) { + const { getV8FastApiCallCount } = internalBinding('debug'); + assert.strictEqual(getV8FastApiCallCount('os.totalmem'), 1); + assert.strictEqual(getV8FastApiCallCount('os.freemem'), 1); + assert.strictEqual(getV8FastApiCallCount('os.availableParallelism'), 1); +}