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

src: enable more detailed memory tracking #21742

Closed
wants to merge 3 commits 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,8 @@
'src/node_revert.h',
'src/node_i18n.h',
'src/node_worker.h',
'src/memory_tracker.h',
'src/memory_tracker-inl.h',
'src/pipe_wrap.h',
'src/tty_wrap.h',
'src/tcp_wrap.h',
Expand Down
21 changes: 17 additions & 4 deletions src/async_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,22 @@ class RetainedAsyncInfo: public RetainedObjectInfo {
private:
const char* label_;
const AsyncWrap* wrap_;
const int length_;
const size_t length_;
};


static int OwnMemory(AsyncWrap* async_wrap) {
MemoryTracker tracker;
tracker.set_track_only_self(true);
tracker.Track(async_wrap);
return tracker.accumulated_size();
}


RetainedAsyncInfo::RetainedAsyncInfo(uint16_t class_id, AsyncWrap* wrap)
: label_(provider_names[class_id - NODE_ASYNC_ID_OFFSET]),
wrap_(wrap),
length_(wrap->self_size()) {
length_(OwnMemory(wrap)) {
}


Expand Down Expand Up @@ -147,7 +155,9 @@ struct AsyncWrapObject : public AsyncWrap {
inline AsyncWrapObject(Environment* env, Local<Object> object,
ProviderType type) : AsyncWrap(env, object, type) {}

inline size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}
};


Expand Down Expand Up @@ -252,7 +262,10 @@ class PromiseWrap : public AsyncWrap {
: AsyncWrap(env, object, PROVIDER_PROMISE, -1, silent) {
MakeWeak();
}
size_t self_size() const override { return sizeof(*this); }

void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}

static constexpr int kPromiseField = 1;
static constexpr int kIsChainedPromiseField = 2;
Expand Down
1 change: 0 additions & 1 deletion src/async_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ class AsyncWrap : public BaseObject {
int argc,
v8::Local<v8::Value>* argv);

virtual size_t self_size() const = 0;
virtual std::string diagnostic_name() const;

static void WeakCallback(const v8::WeakCallbackInfo<DestroyParam> &info);
Expand Down
10 changes: 2 additions & 8 deletions src/base_object-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ Persistent<v8::Object>& BaseObject::persistent() {
}


v8::Local<v8::Object> BaseObject::object() {
v8::Local<v8::Object> BaseObject::object() const {
return PersistentToLocal(env_->isolate(), persistent_handle_);
}

v8::Local<v8::Object> BaseObject::object(v8::Isolate* isolate) {
v8::Local<v8::Object> BaseObject::object(v8::Isolate* isolate) const {
v8::Local<v8::Object> handle = object();
#ifdef DEBUG
CHECK_EQ(handle->CreationContext()->GetIsolate(), isolate);
Expand All @@ -91,12 +91,6 @@ T* BaseObject::FromJSObject(v8::Local<v8::Object> object) {
}


void BaseObject::DeleteMe(void* data) {
BaseObject* self = static_cast<BaseObject*>(data);
delete self;
}


void BaseObject::MakeWeak() {
persistent_handle_.SetWeak(
this,
Expand Down
13 changes: 9 additions & 4 deletions src/base_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include "node_persistent.h"
#include "memory_tracker-inl.h"
#include "v8.h"
#include <type_traits> // std::remove_reference

namespace node {

class Environment;

class BaseObject {
class BaseObject : public MemoryRetainer {
public:
// Associates this object with `object`. It uses the 0th internal field for
// that, and in particular aborts if there is no such field.
Expand All @@ -41,11 +42,11 @@ class BaseObject {

// Returns the wrapped object. Returns an empty handle when
// persistent.IsEmpty() is true.
inline v8::Local<v8::Object> object();
inline v8::Local<v8::Object> object() const;

// Same as the above, except it additionally verifies that this object
// is associated with the passed Isolate in debug mode.
inline v8::Local<v8::Object> object(v8::Isolate* isolate);
inline v8::Local<v8::Object> object(v8::Isolate* isolate) const;

inline Persistent<v8::Object>& persistent();

Expand Down Expand Up @@ -75,14 +76,18 @@ class BaseObject {
private:
BaseObject();

static inline void DeleteMe(void* data);
v8::Local<v8::Object> WrappedObject() const override;
bool IsRootNode() const override;
static void DeleteMe(void* data);

// persistent_handle_ needs to be at a fixed offset from the start of the
// class because it is used by src/node_postmortem_metadata.cc to calculate
// offsets and generate debug symbols for BaseObject, which assumes that the
// position of members in memory are predictable. For more information please
// refer to `doc/guides/node-postmortem-support.md`
friend int GenDebugSymbols();
friend class Environment;

Persistent<v8::Object> persistent_handle_;
Environment* env_;
};
Expand Down
77 changes: 59 additions & 18 deletions src/cares_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,12 @@ inline const char* ToErrorCodeString(int status) {

class ChannelWrap;

struct node_ares_task {
struct node_ares_task : public MemoryRetainer {
ChannelWrap* channel;
ares_socket_t sock;
uv_poll_t poll_watcher;

void MemoryInfo(MemoryTracker* tracker) const override;
};

struct TaskHash {
Expand Down Expand Up @@ -167,7 +169,12 @@ class ChannelWrap : public AsyncWrap {
inline int active_query_count() { return active_query_count_; }
inline node_ares_task_list* task_list() { return &task_list_; }

size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
if (timer_handle_ != nullptr)
tracker->TrackFieldWithSize("timer handle", sizeof(*timer_handle_));
tracker->TrackField("task list", task_list_);
}

static void AresTimeout(uv_timer_t* handle);

Expand All @@ -181,6 +188,11 @@ class ChannelWrap : public AsyncWrap {
node_ares_task_list task_list_;
};

void node_ares_task::MemoryInfo(MemoryTracker* tracker) const {
tracker->TrackThis(this);
tracker->TrackField("channel", channel);
}

ChannelWrap::ChannelWrap(Environment* env,
Local<Object> object)
: AsyncWrap(env, object, PROVIDER_DNSCHANNEL),
Expand Down Expand Up @@ -209,7 +221,10 @@ class GetAddrInfoReqWrap : public ReqWrap<uv_getaddrinfo_t> {
Local<Object> req_wrap_obj,
bool verbatim);

size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}

bool verbatim() const { return verbatim_; }

private:
Expand All @@ -228,7 +243,9 @@ class GetNameInfoReqWrap : public ReqWrap<uv_getnameinfo_t> {
public:
GetNameInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);

size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}
};

GetNameInfoReqWrap::GetNameInfoReqWrap(Environment* env,
Expand Down Expand Up @@ -270,13 +287,13 @@ void ares_poll_cb(uv_poll_t* watcher, int status, int events) {

void ares_poll_close_cb(uv_poll_t* watcher) {
node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
free(task);
delete task;
}


/* Allocates and returns a new node_ares_task */
node_ares_task* ares_task_create(ChannelWrap* channel, ares_socket_t sock) {
auto task = node::UncheckedMalloc<node_ares_task>(1);
auto task = new node_ares_task();

if (task == nullptr) {
/* Out of memory. */
Expand Down Expand Up @@ -1172,7 +1189,9 @@ class QueryAnyWrap: public QueryWrap {
return 0;
}

size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}

protected:
void Parse(unsigned char* buf, int len) override {
Expand Down Expand Up @@ -1349,7 +1368,9 @@ class QueryAWrap: public QueryWrap {
return 0;
}

size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}

protected:
void Parse(unsigned char* buf, int len) override {
Expand Down Expand Up @@ -1393,7 +1414,9 @@ class QueryAaaaWrap: public QueryWrap {
return 0;
}

size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}

protected:
void Parse(unsigned char* buf, int len) override {
Expand Down Expand Up @@ -1437,7 +1460,9 @@ class QueryCnameWrap: public QueryWrap {
return 0;
}

size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}

protected:
void Parse(unsigned char* buf, int len) override {
Expand Down Expand Up @@ -1468,7 +1493,9 @@ class QueryMxWrap: public QueryWrap {
return 0;
}

size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}

protected:
void Parse(unsigned char* buf, int len) override {
Expand Down Expand Up @@ -1499,7 +1526,9 @@ class QueryNsWrap: public QueryWrap {
return 0;
}

size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}

protected:
void Parse(unsigned char* buf, int len) override {
Expand Down Expand Up @@ -1530,7 +1559,9 @@ class QueryTxtWrap: public QueryWrap {
return 0;
}

size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}

protected:
void Parse(unsigned char* buf, int len) override {
Expand Down Expand Up @@ -1560,7 +1591,9 @@ class QuerySrvWrap: public QueryWrap {
return 0;
}

size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}

protected:
void Parse(unsigned char* buf, int len) override {
Expand Down Expand Up @@ -1589,7 +1622,9 @@ class QueryPtrWrap: public QueryWrap {
return 0;
}

size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}

protected:
void Parse(unsigned char* buf, int len) override {
Expand Down Expand Up @@ -1620,7 +1655,9 @@ class QueryNaptrWrap: public QueryWrap {
return 0;
}

size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}

protected:
void Parse(unsigned char* buf, int len) override {
Expand Down Expand Up @@ -1650,7 +1687,9 @@ class QuerySoaWrap: public QueryWrap {
return 0;
}

size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}

protected:
void Parse(unsigned char* buf, int len) override {
Expand Down Expand Up @@ -1729,7 +1768,9 @@ class GetHostByAddrWrap: public QueryWrap {
return 0;
}

size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}

protected:
void Parse(struct hostent* host) override {
Expand Down
4 changes: 3 additions & 1 deletion src/connect_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ class ConnectWrap : public ReqWrap<uv_connect_t> {
v8::Local<v8::Object> req_wrap_obj,
AsyncWrap::ProviderType provider);

size_t self_size() const override { return sizeof(*this); }
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}
};

} // namespace node
Expand Down
14 changes: 14 additions & 0 deletions src/env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -734,4 +734,18 @@ void Environment::stop_sub_worker_contexts() {
}
}

// Not really any better place than env.cc at this moment.
void BaseObject::DeleteMe(void* data) {
BaseObject* self = static_cast<BaseObject*>(data);
delete self;
}

Local<Object> BaseObject::WrappedObject() const {
return object();
}

bool BaseObject::IsRootNode() const {
return !persistent_handle_.IsWeak();
}

} // namespace node
5 changes: 4 additions & 1 deletion src/fs_event_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ class FSEventWrap: public HandleWrap {
static void New(const FunctionCallbackInfo<Value>& args);
static void Start(const FunctionCallbackInfo<Value>& args);
static void GetInitialized(const FunctionCallbackInfo<Value>& args);
size_t self_size() const override { return sizeof(*this); }

void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}

private:
static const encoding kDefaultEncoding = UTF8;
Expand Down
Loading