Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
perf_hooks: fix histogram fast call signatures
  • Loading branch information
Renegade334 committed Aug 23, 2025
commit b47d54b269272b4fd564bf5b69495f29aa2043d1
54 changes: 26 additions & 28 deletions src/histogram.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "base_object-inl.h"
#include "histogram-inl.h"
#include "memory_tracker-inl.h"
#include "node_debug.h"
#include "node_errors.h"
#include "node_external_reference.h"
#include "util.h"
Expand All @@ -11,10 +12,8 @@ namespace node {
using v8::BigInt;
using v8::CFunction;
using v8::Context;
using v8::FastApiCallbackOptions;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::HandleScope;
using v8::Integer;
using v8::Isolate;
using v8::Local;
Expand Down Expand Up @@ -162,8 +161,8 @@ void HistogramBase::RecordDelta(const FunctionCallbackInfo<Value>& args) {
(*histogram)->RecordDelta();
}

void HistogramBase::FastRecordDelta(Local<Value> unused,
Local<Value> receiver) {
void HistogramBase::FastRecordDelta(Local<Value> receiver) {
TRACK_V8_FAST_API_CALL("histogram.recordDelta");
HistogramBase* histogram;
ASSIGN_OR_RETURN_UNWRAP(&histogram, receiver);
(*histogram)->RecordDelta();
Expand All @@ -183,15 +182,9 @@ void HistogramBase::Record(const FunctionCallbackInfo<Value>& args) {
(*histogram)->Record(value);
}

void HistogramBase::FastRecord(Local<Value> unused,
Local<Value> receiver,
const int64_t value,
FastApiCallbackOptions& options) {
if (value < 1) {
HandleScope scope(options.isolate);
THROW_ERR_OUT_OF_RANGE(options.isolate, "value is out of range");
return;
}
Comment on lines -190 to -194
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value is validated in the JS layer, so an assertion should be fine here.

void HistogramBase::FastRecord(Local<Value> receiver, const int64_t value) {
CHECK_GE(value, 1);
TRACK_V8_FAST_API_CALL("histogram.record");
HistogramBase* histogram;
ASSIGN_OR_RETURN_UNWRAP(&histogram, receiver);
(*histogram)->Record(value);
Expand Down Expand Up @@ -428,9 +421,8 @@ void IntervalHistogram::Start(const FunctionCallbackInfo<Value>& args) {
histogram->OnStart(args[0]->IsTrue() ? StartFlags::RESET : StartFlags::NONE);
}

void IntervalHistogram::FastStart(Local<Value> unused,
Local<Value> receiver,
bool reset) {
void IntervalHistogram::FastStart(Local<Value> receiver, bool reset) {
TRACK_V8_FAST_API_CALL("histogram.start");
IntervalHistogram* histogram;
ASSIGN_OR_RETURN_UNWRAP(&histogram, receiver);
histogram->OnStart(reset ? StartFlags::RESET : StartFlags::NONE);
Expand All @@ -442,7 +434,8 @@ void IntervalHistogram::Stop(const FunctionCallbackInfo<Value>& args) {
histogram->OnStop();
}

void IntervalHistogram::FastStop(Local<Value> unused, Local<Value> receiver) {
void IntervalHistogram::FastStop(Local<Value> receiver) {
TRACK_V8_FAST_API_CALL("histogram.stop");
IntervalHistogram* histogram;
ASSIGN_OR_RETURN_UNWRAP(&histogram, receiver);
histogram->OnStop();
Expand Down Expand Up @@ -558,46 +551,51 @@ void HistogramImpl::DoReset(const FunctionCallbackInfo<Value>& args) {
(*histogram)->Reset();
}

void HistogramImpl::FastReset(Local<Value> unused, Local<Value> receiver) {
void HistogramImpl::FastReset(Local<Value> receiver) {
TRACK_V8_FAST_API_CALL("histogram.reset");
HistogramImpl* histogram = HistogramImpl::FromJSObject(receiver);
(*histogram)->Reset();
}

double HistogramImpl::FastGetCount(Local<Value> unused, Local<Value> receiver) {
double HistogramImpl::FastGetCount(Local<Value> receiver) {
TRACK_V8_FAST_API_CALL("histogram.count");
HistogramImpl* histogram = HistogramImpl::FromJSObject(receiver);
return static_cast<double>((*histogram)->Count());
}

double HistogramImpl::FastGetMin(Local<Value> unused, Local<Value> receiver) {
double HistogramImpl::FastGetMin(Local<Value> receiver) {
TRACK_V8_FAST_API_CALL("histogram.min");
HistogramImpl* histogram = HistogramImpl::FromJSObject(receiver);
return static_cast<double>((*histogram)->Min());
}

double HistogramImpl::FastGetMax(Local<Value> unused, Local<Value> receiver) {
double HistogramImpl::FastGetMax(Local<Value> receiver) {
TRACK_V8_FAST_API_CALL("histogram.max");
HistogramImpl* histogram = HistogramImpl::FromJSObject(receiver);
return static_cast<double>((*histogram)->Max());
}

double HistogramImpl::FastGetMean(Local<Value> unused, Local<Value> receiver) {
double HistogramImpl::FastGetMean(Local<Value> receiver) {
TRACK_V8_FAST_API_CALL("histogram.mean");
HistogramImpl* histogram = HistogramImpl::FromJSObject(receiver);
return (*histogram)->Mean();
}

double HistogramImpl::FastGetExceeds(Local<Value> unused,
Local<Value> receiver) {
double HistogramImpl::FastGetExceeds(Local<Value> receiver) {
TRACK_V8_FAST_API_CALL("histogram.exceeds");
HistogramImpl* histogram = HistogramImpl::FromJSObject(receiver);
return static_cast<double>((*histogram)->Exceeds());
}

double HistogramImpl::FastGetStddev(Local<Value> unused,
Local<Value> receiver) {
double HistogramImpl::FastGetStddev(Local<Value> receiver) {
TRACK_V8_FAST_API_CALL("histogram.stddev");
HistogramImpl* histogram = HistogramImpl::FromJSObject(receiver);
return (*histogram)->Stddev();
}

double HistogramImpl::FastGetPercentile(Local<Value> unused,
Local<Value> receiver,
double HistogramImpl::FastGetPercentile(Local<Value> receiver,
const double percentile) {
TRACK_V8_FAST_API_CALL("histogram.percentile");
HistogramImpl* histogram = HistogramImpl::FromJSObject(receiver);
return static_cast<double>((*histogram)->Percentile(percentile));
}
Expand Down
40 changes: 12 additions & 28 deletions src/histogram.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,22 +101,14 @@ class HistogramImpl {
static void GetPercentilesBigInt(
const v8::FunctionCallbackInfo<v8::Value>& args);

static void FastReset(v8::Local<v8::Value> unused,
v8::Local<v8::Value> receiver);
static double FastGetCount(v8::Local<v8::Value> unused,
v8::Local<v8::Value> receiver);
static double FastGetMin(v8::Local<v8::Value> unused,
v8::Local<v8::Value> receiver);
static double FastGetMax(v8::Local<v8::Value> unused,
v8::Local<v8::Value> receiver);
static double FastGetMean(v8::Local<v8::Value> unused,
v8::Local<v8::Value> receiver);
static double FastGetExceeds(v8::Local<v8::Value> unused,
v8::Local<v8::Value> receiver);
static double FastGetStddev(v8::Local<v8::Value> unused,
v8::Local<v8::Value> receiver);
static double FastGetPercentile(v8::Local<v8::Value> unused,
v8::Local<v8::Value> receiver,
static void FastReset(v8::Local<v8::Value> receiver);
static double FastGetCount(v8::Local<v8::Value> receiver);
static double FastGetMin(v8::Local<v8::Value> receiver);
static double FastGetMax(v8::Local<v8::Value> receiver);
static double FastGetMean(v8::Local<v8::Value> receiver);
static double FastGetExceeds(v8::Local<v8::Value> receiver);
static double FastGetStddev(v8::Local<v8::Value> receiver);
static double FastGetPercentile(v8::Local<v8::Value> receiver,
const double percentile);

static void AddMethods(v8::Isolate* isolate,
Expand Down Expand Up @@ -165,13 +157,8 @@ class HistogramBase final : public BaseObject, public HistogramImpl {
static void RecordDelta(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Add(const v8::FunctionCallbackInfo<v8::Value>& args);

static void FastRecord(
v8::Local<v8::Value> unused,
v8::Local<v8::Value> receiver,
const int64_t value,
v8::FastApiCallbackOptions& options); // NOLINT(runtime/references)
static void FastRecordDelta(v8::Local<v8::Value> unused,
v8::Local<v8::Value> receiver);
static void FastRecord(v8::Local<v8::Value> receiver, const int64_t value);
static void FastRecordDelta(v8::Local<v8::Value> receiver);

HistogramBase(
Environment* env,
Expand Down Expand Up @@ -243,11 +230,8 @@ class IntervalHistogram final : public HandleWrap, public HistogramImpl {
static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Stop(const v8::FunctionCallbackInfo<v8::Value>& args);

static void FastStart(v8::Local<v8::Value> unused,
v8::Local<v8::Value> receiver,
bool reset);
static void FastStop(v8::Local<v8::Value> unused,
v8::Local<v8::Value> receiver);
static void FastStart(v8::Local<v8::Value> receiver, bool reset);
static void FastStop(v8::Local<v8::Value> receiver);

BaseObject::TransferMode GetTransferMode() const override {
return TransferMode::kCloneable;
Expand Down
35 changes: 35 additions & 0 deletions test/parallel/test-perf-hooks-histogram-fast-calls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Flags: --expose-internals --no-warnings --allow-natives-syntax
'use strict';

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

const { internalBinding } = require('internal/test/binding');

const histogram = require('perf_hooks').createHistogram();

function testFastMethods() {
histogram.record(1);
histogram.recordDelta();
histogram.percentile(50);
histogram.reset();
}

eval('%PrepareFunctionForOptimization(histogram.record)');
eval('%PrepareFunctionForOptimization(histogram.recordDelta)');
eval('%PrepareFunctionForOptimization(histogram.percentile)');
eval('%PrepareFunctionForOptimization(histogram.reset)');
testFastMethods();
eval('%OptimizeFunctionOnNextCall(histogram.record)');
eval('%OptimizeFunctionOnNextCall(histogram.recordDelta)');
eval('%OptimizeFunctionOnNextCall(histogram.percentile)');
eval('%OptimizeFunctionOnNextCall(histogram.reset)');
testFastMethods();

if (common.isDebug) {
const { getV8FastApiCallCount } = internalBinding('debug');
assert.strictEqual(getV8FastApiCallCount('histogram.record'), 1);
assert.strictEqual(getV8FastApiCallCount('histogram.recordDelta'), 1);
assert.strictEqual(getV8FastApiCallCount('histogram.percentile'), 1);
assert.strictEqual(getV8FastApiCallCount('histogram.reset'), 1);
}
6 changes: 4 additions & 2 deletions test/parallel/test-perf-hooks-histogram.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ const { inspect } = require('util');
code: 'ERR_INVALID_ARG_TYPE'
});
});
throws(() => h.record(0, Number.MAX_SAFE_INTEGER + 1), {
code: 'ERR_OUT_OF_RANGE'
[0, Number.MAX_SAFE_INTEGER + 1].forEach((i) => {
throws(() => h.record(i), {
code: 'ERR_OUT_OF_RANGE'
});
});

strictEqual(h.min, 1);
Expand Down