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 memory mangament feature #286

Closed
wants to merge 2 commits into from
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ values. Concepts and operations generally map to ideas specified in the
- [ArrayBuffer](doc/array_buffer.md)
- [TypedArray](doc/typed_array.md)
- [TypedArrayOf](doc/typed_array_of.md)
- [Memory Management](doc/memory_management.md)
- [Async Operations](doc/async_operations.md)
- [AsyncWorker](doc/async_worker.md)
- [Promises](doc/promises.md)
Expand Down
27 changes: 27 additions & 0 deletions doc/memory_management.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# MemoryManagement

The `MemoryManagement` class contains functions that give the JavaScript engine
an indication of the amount of externally allocated memory that is kept alive by
JavaScript objects.

## Methods

### AdjustExternalMemory

The function `AdjustExternalMemory` adjusts the amount of registered external
memory. Used to give the JavaScript engine an indication of the amount of externally
Copy link
Contributor

Choose a reason for hiding this comment

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

"[It is ]Uused ..."

allocated memory that is kept alive by JavaScript objects.
The JavaScript engine uses this to decide when to perform global garbage collections.
Registering externally allocated memory will trigger global garbage collections
more often than it would otherwise in an attempt to garbage collect the JavaScript
objects that keep the externally allocated memory alive.

```cpp
static int64_t MemoryManagement::AdjustExternalMemory(Env env, int64_t change_in_bytes);
```

- `[in] env`: The environment in which the API is inoked under.
Copy link
Contributor

Choose a reason for hiding this comment

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

"in[v]oked"

- `[in] change_in_bytes`: The change in externally allocated memory that is kept
alive by JavaScript objects expressed in bytes.

Returns the adjusted memory value.
11 changes: 11 additions & 0 deletions napi-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3224,6 +3224,17 @@ inline void AsyncWorker::OnWorkComplete(
delete self;
}

////////////////////////////////////////////////////////////////////////////////
// Memory Management class
////////////////////////////////////////////////////////////////////////////////

inline int64_t MemoryManagement::AdjustExternalMemory(Env env, int64_t change_in_bytes) {
int64_t result;
napi_status status = napi_adjust_external_memory(env, change_in_bytes, &result);
NAPI_THROW_IF_FAILED(env, status, 0);
return result;
}

// These macros shouldn't be useful in user code.
#undef NAPI_THROW
#undef NAPI_THROW_IF_FAILED
Expand Down
8 changes: 8 additions & 0 deletions napi.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ namespace Napi {
/// Defines the signature of a N-API C++ module's registration callback (init) function.
typedef Object (*ModuleRegisterCallback)(Env env, Object exports);

class MemoryManagement;

/// Environment for N-API values and operations.
///
/// All N-API values and operations must be associated with an environment. An environment
Expand Down Expand Up @@ -1549,6 +1551,12 @@ namespace Napi {
std::string _error;
};

// Memory management.
class MemoryManagement {
public:
static int64_t AdjustExternalMemory(Env env, int64_t change_in_bytes);
};

} // namespace Napi

// Inline implementations of all the above class methods are included here.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"Anna Henningsen (https://github.com/addaleax)",
"Arunesh Chandra (https://github.com/aruneshchandra)",
"Benjamin Byholm (https://github.com/kkoopa)",
"Cory Mickelson (https://github.com/corymickelson)",
"Cory Mickelson (https://github.com/corymickelson)",
"David Halls (https://github.com/davedoesdev)",
"Eric Bickle (https://github.com/ebickle)",
"Gabriel Schulhof (https://github.com/gabrielschulhof)",
Expand Down
2 changes: 2 additions & 0 deletions test/binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Object InitError(Env env);
Object InitExternal(Env env);
Object InitFunction(Env env);
Object InitHandleScope(Env env);
Object InitMemoryManagement(Env env);
Object InitName(Env env);
Object InitObject(Env env);
Object InitPromise(Env env);
Expand All @@ -33,6 +34,7 @@ Object Init(Env env, Object exports) {
exports.Set("function", InitFunction(env));
exports.Set("name", InitName(env));
exports.Set("handlescope", InitHandleScope(env));
exports.Set("memory_management", InitMemoryManagement(env));
exports.Set("object", InitObject(env));
exports.Set("promise", InitPromise(env));
exports.Set("typedarray", InitTypedArray(env));
Expand Down
1 change: 1 addition & 0 deletions test/binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
'external.cc',
'function.cc',
'handlescope.cc',
'memory_management.cc',
'name.cc',
'object/delete_property.cc',
'object/get_property.cc',
Expand Down
1 change: 1 addition & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ let testModules = [
'external',
'function',
'handlescope',
'memory_management',
'name',
'object/delete_property',
'object/get_property',
Expand Down
17 changes: 17 additions & 0 deletions test/memory_management.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "napi.h"

using namespace Napi;

Value externalAllocatedMemory(const CallbackInfo& info) {
int64_t kSize = 1024 * 1024;
int64_t baseline = MemoryManagement::AdjustExternalMemory(info.Env(), 0);
int64_t tmp = MemoryManagement::AdjustExternalMemory(info.Env(), kSize);
tmp = MemoryManagement::AdjustExternalMemory(info.Env(), -kSize);
return Boolean::New(info.Env(), tmp == baseline);
}

Object InitMemoryManagement(Env env) {
Object exports = Object::New(env);
exports["externalAllocatedMemory"] = Function::New(env, externalAllocatedMemory);
return exports;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add a newline to the end of the file!

10 changes: 10 additions & 0 deletions test/memory_management.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict';
const buildType = process.config.target_defaults.default_configuration;
const assert = require('assert');

test(require(`./build/${buildType}/binding.node`));
test(require(`./build/${buildType}/binding_noexcept.node`));

function test(binding) {
assert.strictEqual(binding.memory_management.externalAllocatedMemory(), true)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Ditto.