Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

timers: use V8 fast API calls #46579

Merged
merged 1 commit into from
Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 27 additions & 17 deletions lib/internal/timers.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,11 @@ const {
Symbol,
} = primordials;

const binding = internalBinding('timers');
const {
scheduleTimer,
toggleTimerRef,
getLibuvNow,
immediateInfo,
timeoutInfo,
toggleImmediateRef,
} = internalBinding('timers');
} = binding;

const {
getDefaultTriggerAsyncId,
Expand Down Expand Up @@ -306,13 +303,17 @@ class ImmediateList {
const immediateQueue = new ImmediateList();

function incRefCount() {
if (timeoutInfo[0]++ === 0)
toggleTimerRef(true);
if (timeoutInfo[0]++ === 0) {
// We need to use the binding as the receiver for fast API calls.
binding.toggleTimerRef(true);
}
}

function decRefCount() {
if (--timeoutInfo[0] === 0)
toggleTimerRef(false);
if (--timeoutInfo[0] === 0) {
// We need to use the binding as the receiver for fast API calls.
binding.toggleTimerRef(false);
}
}

// Schedule or re-schedule a timer.
Expand Down Expand Up @@ -356,7 +357,8 @@ function insertGuarded(item, refed, start) {
item[kRefed] = refed;
}

function insert(item, msecs, start = getLibuvNow()) {
// We need to use the binding as the receiver for fast API calls.
function insert(item, msecs, start = binding.getLibuvNow()) {
// Truncate so that accuracy of sub-millisecond timers is not assumed.
msecs = MathTrunc(msecs);
item._idleStart = start;
Expand All @@ -370,7 +372,8 @@ function insert(item, msecs, start = getLibuvNow()) {
timerListQueue.insert(list);

if (nextExpiry > expiry) {
scheduleTimer(msecs);
// We need to use the binding as the receiver for fast API calls.
binding.scheduleTimer(msecs);
nextExpiry = expiry;
}
}
Expand Down Expand Up @@ -559,8 +562,10 @@ function getTimerCallbacks(runNextTicks) {
emitBefore(asyncId, timer[trigger_async_id_symbol], timer);

let start;
if (timer._repeat)
start = getLibuvNow();
if (timer._repeat) {
// We need to use the binding as the receiver for fast API calls.
start = binding.getLibuvNow();
}

try {
const args = timer._timerArgs;
Expand Down Expand Up @@ -627,17 +632,22 @@ class Immediate {
ref() {
if (this[kRefed] === false) {
this[kRefed] = true;
if (immediateInfo[kRefCount]++ === 0)
toggleImmediateRef(true);

if (immediateInfo[kRefCount]++ === 0) {
// We need to use the binding as the receiver for fast API calls.
binding.toggleImmediateRef(true);
}
}
return this;
}

unref() {
if (this[kRefed] === true) {
this[kRefed] = false;
if (--immediateInfo[kRefCount] === 0)
toggleImmediateRef(false);
if (--immediateInfo[kRefCount] === 0) {
// We need to use the binding as the receiver for fast API calls.
binding.toggleImmediateRef(false);
}
}
return this;
}
Expand Down
10 changes: 6 additions & 4 deletions lib/timers.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ const {
SymbolToPrimitive
} = primordials;

const binding = internalBinding('timers');
const {
immediateInfo,
toggleImmediateRef
} = internalBinding('timers');
} = binding;
const L = require('internal/linkedlist');
const {
async_id_symbol,
Expand Down Expand Up @@ -323,8 +323,10 @@ function clearImmediate(immediate) {
immediateInfo[kCount]--;
immediate._destroyed = true;

if (immediate[kRefed] && --immediateInfo[kRefCount] === 0)
toggleImmediateRef(false);
if (immediate[kRefed] && --immediateInfo[kRefCount] === 0) {
// We need to use the binding as the receiver for fast API calls.
binding.toggleImmediateRef(false);
}
immediate[kRefed] = null;

if (destroyHooksExist() && immediate[async_id_symbol] !== undefined) {
Expand Down
1 change: 1 addition & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,7 @@
'src/string_decoder-inl.h',
'src/string_search.h',
'src/tcp_wrap.h',
'src/timers.h',
'src/tracing/agent.h',
'src/tracing/node_trace_buffer.h',
'src/tracing/node_trace_writer.h',
Expand Down
3 changes: 2 additions & 1 deletion src/base_object_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ namespace node {
V(fs_binding_data, fs::BindingData) \
V(v8_binding_data, v8_utils::BindingData) \
V(blob_binding_data, BlobBindingData) \
V(process_binding_data, process::BindingData)
V(process_binding_data, process::BindingData) \
V(timers_binding_data, timers::BindingData)

#define UNSERIALIZABLE_BINDING_TYPES(V) \
V(http2_binding_data, http2::BindingData) \
Expand Down
8 changes: 6 additions & 2 deletions src/env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1299,12 +1299,16 @@ void Environment::ToggleImmediateRef(bool ref) {
}
}


Local<Value> Environment::GetNow() {
uint64_t Environment::GetNowUint64() {
uv_update_time(event_loop());
uint64_t now = uv_now(event_loop());
CHECK_GE(now, timer_base());
now -= timer_base();
return now;
}

Local<Value> Environment::GetNow() {
uint64_t now = GetNowUint64();
if (now <= 0xffffffff)
return Integer::NewFromUnsigned(isolate(), static_cast<uint32_t>(now));
else
Expand Down
2 changes: 2 additions & 0 deletions src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,8 @@ class Environment : public MemoryRetainer {
static inline Environment* ForAsyncHooks(AsyncHooks* hooks);

v8::Local<v8::Value> GetNow();
uint64_t GetNowUint64();

void ScheduleTimer(int64_t duration);
void ToggleTimerRef(bool ref);

Expand Down
9 changes: 9 additions & 0 deletions src/node_external_reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ namespace node {
using CFunctionCallbackWithOneByteString =
uint32_t (*)(v8::Local<v8::Value>, const v8::FastOneByteString&);
using CFunctionCallback = void (*)(v8::Local<v8::Value> receiver);
using CFunctionCallbackReturnDouble =
double (*)(v8::Local<v8::Object> receiver);
using CFunctionCallbackWithInt64 = void (*)(v8::Local<v8::Object> receiver,
int64_t);
using CFunctionCallbackWithBool = void (*)(v8::Local<v8::Object> receiver,
bool);

// This class manages the external references from the V8 heap
// to the C++ addresses in Node.js.
Expand All @@ -23,6 +29,9 @@ class ExternalReferenceRegistry {
#define ALLOWED_EXTERNAL_REFERENCE_TYPES(V) \
V(CFunctionCallback) \
V(CFunctionCallbackWithOneByteString) \
V(CFunctionCallbackReturnDouble) \
V(CFunctionCallbackWithInt64) \
V(CFunctionCallbackWithBool) \
V(const v8::CFunctionInfo*) \
V(v8::FunctionCallback) \
V(v8::AccessorGetterCallback) \
Expand Down
1 change: 1 addition & 0 deletions src/node_snapshotable.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "node_util.h"
#include "node_v8.h"
#include "node_v8_platform-inl.h"
#include "timers.h"

#if HAVE_INSPECTOR
#include "inspector/worker_inspector.h" // ParentInspectorHandle
Expand Down
Loading