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

Add direct access to rss without iterating pages #34291

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 22 additions & 0 deletions doc/api/process.md
Expand Up @@ -1589,6 +1589,28 @@ Will generate:
When using [`Worker`][] threads, `rss` will be a value that is valid for the
entire process, while the other fields will only refer to the current thread.

The `process.memoryUsage()` method iterate over each page to gather
informations about memory usage which can be slow depending on the
Copy link
Member

Choose a reason for hiding this comment

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

I find can be slow quite vague - in special as a caller can't do anything to avoid this to test if it will be slow.
Are we talking about µs, ms, or seconds here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It depends on the program size in memory. Access the RSS take a fixed time but compute heap statistics is quite costly since you have to iterate over every memory page.
The difference can be in seconds. (see the benchmark in the PR description)

Copy link
Member

Choose a reason for hiding this comment

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

The sample in PR description prints milli seconds not seconds so not that bad.
I tried it local on my machine and even for 4GB heaps it was below 0.2ms. But for sure the rss only API is much faster.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

At the beginning I have done this PR because I found very strange results while benchmarking promises (#33384).
So even if the difference is not that huge it can be misleading in some cases

program memory allocations.

## `process.memoryUsage.rss()`

* Returns: {integer}

The `process.memoryUsage.rss()` method returns an integer representing the
Resident Set Size (RSS) in bytes.

The Resident Set Size, is the amount of space occupied in the main
memory device (that is a subset of the total allocated memory) for the
process, including all C++ and JavaScript objects and code.
Flarna marked this conversation as resolved.
Show resolved Hide resolved

This is the same value as the one returned by `process.memoryUsage()`.

```js
console.log(process.memoryUsage.rss());
// 35655680
```

## `process.nextTick(callback[, ...args])`
<!-- YAML
added: v0.1.26
Expand Down
3 changes: 3 additions & 0 deletions lib/internal/process/per_thread.js
Expand Up @@ -93,6 +93,7 @@ function wrapProcessMethods(binding) {
const {
cpuUsage: _cpuUsage,
memoryUsage: _memoryUsage,
rss,
resourceUsage: _resourceUsage
} = binding;

Expand Down Expand Up @@ -168,6 +169,8 @@ function wrapProcessMethods(binding) {
};
}

memoryUsage.rss = rss;

function exit(code) {
if (code || code === 0)
process.exitCode = code;
Expand Down
15 changes: 14 additions & 1 deletion src/node_process_methods.cc
Expand Up @@ -172,14 +172,20 @@ static void Kill(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(err);
}

static void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
static void Rss(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);

size_t rss;
int err = uv_resident_set_memory(&rss);
if (err)
return env->ThrowUVException(err, "uv_resident_set_memory");

args.GetReturnValue().Set(static_cast<double>(rss));
}
jasnell marked this conversation as resolved.
Show resolved Hide resolved

static void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);

Isolate* isolate = env->isolate();
// V8 memory usage
HeapStatistics v8_heap_stats;
Expand All @@ -192,6 +198,11 @@ static void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
Local<ArrayBuffer> ab = get_fields_array_buffer(args, 0, 5);
double* fields = static_cast<double*>(ab->GetBackingStore()->Data());

size_t rss;
int err = uv_resident_set_memory(&rss);
if (err)
return env->ThrowUVException(err, "uv_resident_set_memory");

fields[0] = rss;
fields[1] = v8_heap_stats.total_heap_size();
fields[2] = v8_heap_stats.used_heap_size();
Expand Down Expand Up @@ -542,6 +553,7 @@ static void InitializeProcessMethods(Local<Object> target,
env->SetMethod(target, "umask", Umask);
env->SetMethod(target, "_rawDebug", RawDebug);
env->SetMethod(target, "memoryUsage", MemoryUsage);
env->SetMethod(target, "rss", Rss);
env->SetMethod(target, "cpuUsage", CPUUsage);
env->SetMethod(target, "resourceUsage", ResourceUsage);

Expand All @@ -568,6 +580,7 @@ void RegisterProcessMethodsExternalReferences(
registry->Register(Umask);
registry->Register(RawDebug);
registry->Register(MemoryUsage);
registry->Register(Rss);
registry->Register(CPUUsage);
registry->Register(ResourceUsage);

Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-memory-usage.js
Expand Up @@ -44,3 +44,5 @@ if (r.arrayBuffers > 0) {
assert.strictEqual(after.arrayBuffers - r.arrayBuffers, size,
`${after.arrayBuffers} - ${r.arrayBuffers} === ${size}`);
}

assert(process.memoryUsage.rss() > 0);