Created
December 1, 2016 22:28
-
-
Save trevnorris/ac05bbbef5433c7701b492e8c71352b8 to your computer and use it in GitHub Desktop.
Example of returning all values from uv_rusage() as tuples w/ no overhead. Values are only valid until getrusage() is called again.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"targets": [{ | |
"target_name": "addon", | |
"sources": [ "main.cc" ] | |
}] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <v8.h> | |
#include <node.h> | |
#include <uv.h> | |
#define RUSAGE_FIELDS(V) \ | |
V(ru_maxrss) \ | |
V(ru_ixrss) \ | |
V(ru_idrss) \ | |
V(ru_isrss) \ | |
V(ru_minflt) \ | |
V(ru_majflt) \ | |
V(ru_nswap) \ | |
V(ru_inblock) \ | |
V(ru_oublock) \ | |
V(ru_msgsnd) \ | |
V(ru_msgrcv) \ | |
V(ru_nsignals) \ | |
V(ru_nvcsw) \ | |
V(ru_nivcsw) | |
// Depends on the Isolate being named "isolate" and Local<Context> being | |
// named "context". Bad me! | |
#define FORCE_SET_PROP(obj, key, val) \ | |
obj->ForceSet( \ | |
context, NewFromOneByte(isolate, key), val, v8::ReadOnly).FromJust() | |
namespace bmod { | |
using namespace v8; | |
Eternal<Uint32Array> rusage_array_e; | |
enum rusage_fields { | |
#define V(field) \ | |
field, | |
RUSAGE_FIELDS(V) | |
#undef V | |
ru_utime, | |
ru_stime, | |
rusage_length, | |
}; | |
static Local<String> NewFromOneByte(Isolate* isolate, const char* name) { | |
EscapableHandleScope escope(isolate); | |
const NewStringType type = NewStringType::kInternalized; | |
Local<String> t_name = | |
String::NewFromOneByte(isolate, | |
reinterpret_cast<const uint8_t*>(name), | |
type).ToLocalChecked(); | |
return escope.Escape(t_name); | |
} | |
void Setup(const FunctionCallbackInfo<Value>& args) { | |
Isolate* isolate = args.GetIsolate(); | |
Local<Context> context = isolate->GetCurrentContext(); | |
Local<Object> constants = Object::New(isolate); | |
#define V(field) \ | |
FORCE_SET_PROP(constants, \ | |
#field, \ | |
Integer::New(isolate, rusage_fields::field)); | |
RUSAGE_FIELDS(V) | |
#undef V | |
FORCE_SET_PROP(constants, | |
"ru_utime", | |
Integer::New(isolate, rusage_fields::ru_utime)); | |
FORCE_SET_PROP(constants, | |
"ru_stime", | |
Integer::New(isolate, rusage_fields::ru_stime)); | |
Local<ArrayBuffer> rusage_ab = | |
ArrayBuffer::New(isolate, | |
rusage_fields::rusage_length * sizeof(uint32_t) * 2); | |
Local<Uint32Array> rusage_array = | |
Uint32Array::New(rusage_ab, 0, rusage_fields::rusage_length * 2); | |
rusage_array_e.Set(isolate, rusage_array); | |
FORCE_SET_PROP(constants, "rusage_array", rusage_array); | |
Local<Object> return_obj = Object::New(isolate); | |
#define V(field) \ | |
FORCE_SET_PROP( \ | |
return_obj, #field, Uint32Array::New( \ | |
rusage_ab, rusage_fields::field * sizeof(uint32_t) * 2, 2)); | |
RUSAGE_FIELDS(V) | |
#undef V | |
FORCE_SET_PROP( | |
return_obj, "ru_utime", Uint32Array::New( | |
rusage_ab, rusage_fields::ru_utime * sizeof(uint32_t) * 2, 2)); | |
FORCE_SET_PROP( | |
return_obj, "ru_stime", Uint32Array::New( | |
rusage_ab, rusage_fields::ru_stime * sizeof(uint32_t) * 2, 2)); | |
FORCE_SET_PROP(constants, "return_obj", return_obj); | |
args.GetReturnValue().Set(constants); | |
} | |
void GetRusage(const FunctionCallbackInfo<Value>& args) { | |
Isolate* isolate = args.GetIsolate(); | |
uv_rusage_t ru; | |
int err; | |
err = uv_getrusage(&ru); | |
if (err) { | |
fprintf(stderr, "uv_getrusage error\n"); | |
return; | |
} | |
uint32_t* data_array = static_cast<uint32_t*>( | |
rusage_array_e.Get(isolate)->Buffer()->GetContents().Data()); | |
#define V(field) \ | |
data_array[rusage_fields::field * 2] = ru.field & 0xFFFFFFFF; \ | |
data_array[rusage_fields::field * 2 + 1] = ru.field >> 32; | |
RUSAGE_FIELDS(V) | |
#undef V | |
data_array[rusage_fields::ru_utime * 2] = ru.ru_utime.tv_sec; | |
data_array[rusage_fields::ru_utime * 2 + 1] = ru.ru_utime.tv_usec; | |
data_array[rusage_fields::ru_stime * 2] = ru.ru_stime.tv_sec; | |
data_array[rusage_fields::ru_stime * 2 + 1] = ru.ru_stime.tv_usec; | |
} | |
void init(Handle<Object> exports) { | |
NODE_SET_METHOD(exports, "setup", Setup); | |
NODE_SET_METHOD(exports, "getRusage", GetRusage); | |
} | |
} // namespace bmod | |
NODE_MODULE(addon, bmod::init) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const addon = require('./build/Release/addon'); | |
const print = process._rawDebug; | |
const data_obj = addon.setup(); | |
const frozen_return_obj = Object.freeze(data_obj.return_obj); | |
// Return a frozen object that contains all the uint64_t fields of | |
// uv_getrusage() as a tuple from slices of a single Uint32Array and allow | |
// the user to retrieve/convert only the values they're looking for. The | |
// returned values must be copied out because they're only guaranteed for | |
// the duration of the function call. | |
function getrusage() { | |
addon.getRusage(); | |
return frozen_return_obj; | |
} | |
// Convert a uint32 tuple into a double. Useful if exact precision isn't | |
// needed. | |
function two32ToDouble(tuple) { | |
return tuple[0] + tuple[1] * 0x100000000; | |
} | |
const ITER = 1e6; | |
var t = process.hrtime(); | |
(function runner() { | |
for (var i = 0; i < ITER; i++) { | |
// Every time getrusage() is called the previous set of values is | |
// overwritten. | |
const obj = getrusage(); | |
two32ToDouble(obj.ru_maxrss); | |
} | |
})(); | |
printTime(); | |
print(getrusage()); | |
function printTime() { | |
t = process.hrtime(t); | |
print(((t[0] * 1e9 + t[1]) / ITER).toFixed(1) + ' ns/op'); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment