Skip to content

Commit 712809e

Browse files
addaleaxtargos
authored andcommitted
src: enable more detailed memory tracking
This will enable more detailed heap snapshots based on a newer V8 API. This commit itself is not tied to that API and could be backported. PR-URL: #21742 Reviewed-By: James M Snell <[email protected]>
1 parent f46536b commit 712809e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+566
-91
lines changed

node.gyp

+2
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,8 @@
420420
'src/node_revert.h',
421421
'src/node_i18n.h',
422422
'src/node_worker.h',
423+
'src/memory_tracker.h',
424+
'src/memory_tracker-inl.h',
423425
'src/pipe_wrap.h',
424426
'src/tty_wrap.h',
425427
'src/tcp_wrap.h',

src/async_wrap.cc

+17-4
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,22 @@ class RetainedAsyncInfo: public RetainedObjectInfo {
7676
private:
7777
const char* label_;
7878
const AsyncWrap* wrap_;
79-
const int length_;
79+
const size_t length_;
8080
};
8181

8282

83+
static int OwnMemory(AsyncWrap* async_wrap) {
84+
MemoryTracker tracker;
85+
tracker.set_track_only_self(true);
86+
tracker.Track(async_wrap);
87+
return tracker.accumulated_size();
88+
}
89+
90+
8391
RetainedAsyncInfo::RetainedAsyncInfo(uint16_t class_id, AsyncWrap* wrap)
8492
: label_(provider_names[class_id - NODE_ASYNC_ID_OFFSET]),
8593
wrap_(wrap),
86-
length_(wrap->self_size()) {
94+
length_(OwnMemory(wrap)) {
8795
}
8896

8997

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

150-
inline size_t self_size() const override { return sizeof(*this); }
158+
void MemoryInfo(MemoryTracker* tracker) const override {
159+
tracker->TrackThis(this);
160+
}
151161
};
152162

153163

@@ -252,7 +262,10 @@ class PromiseWrap : public AsyncWrap {
252262
: AsyncWrap(env, object, PROVIDER_PROMISE, -1, silent) {
253263
MakeWeak();
254264
}
255-
size_t self_size() const override { return sizeof(*this); }
265+
266+
void MemoryInfo(MemoryTracker* tracker) const override {
267+
tracker->TrackThis(this);
268+
}
256269

257270
static constexpr int kPromiseField = 1;
258271
static constexpr int kIsChainedPromiseField = 2;

src/async_wrap.h

-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ class AsyncWrap : public BaseObject {
174174
int argc,
175175
v8::Local<v8::Value>* argv);
176176

177-
virtual size_t self_size() const = 0;
178177
virtual std::string diagnostic_name() const;
179178

180179
static void WeakCallback(const v8::WeakCallbackInfo<DestroyParam> &info);

src/base_object-inl.h

+2-8
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ Persistent<v8::Object>& BaseObject::persistent() {
6161
}
6262

6363

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

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

9393

94-
void BaseObject::DeleteMe(void* data) {
95-
BaseObject* self = static_cast<BaseObject*>(data);
96-
delete self;
97-
}
98-
99-
10094
void BaseObject::MakeWeak() {
10195
persistent_handle_.SetWeak(
10296
this,

src/base_object.h

+9-4
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,15 @@
2525
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
2626

2727
#include "node_persistent.h"
28+
#include "memory_tracker-inl.h"
2829
#include "v8.h"
2930
#include <type_traits> // std::remove_reference
3031

3132
namespace node {
3233

3334
class Environment;
3435

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

4243
// Returns the wrapped object. Returns an empty handle when
4344
// persistent.IsEmpty() is true.
44-
inline v8::Local<v8::Object> object();
45+
inline v8::Local<v8::Object> object() const;
4546

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

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

@@ -75,14 +76,18 @@ class BaseObject {
7576
private:
7677
BaseObject();
7778

78-
static inline void DeleteMe(void* data);
79+
v8::Local<v8::Object> WrappedObject() const override;
80+
bool IsRootNode() const override;
81+
static void DeleteMe(void* data);
7982

8083
// persistent_handle_ needs to be at a fixed offset from the start of the
8184
// class because it is used by src/node_postmortem_metadata.cc to calculate
8285
// offsets and generate debug symbols for BaseObject, which assumes that the
8386
// position of members in memory are predictable. For more information please
8487
// refer to `doc/guides/node-postmortem-support.md`
8588
friend int GenDebugSymbols();
89+
friend class Environment;
90+
8691
Persistent<v8::Object> persistent_handle_;
8792
Environment* env_;
8893
};

src/cares_wrap.cc

+59-18
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,12 @@ inline const char* ToErrorCodeString(int status) {
121121

122122
class ChannelWrap;
123123

124-
struct node_ares_task {
124+
struct node_ares_task : public MemoryRetainer {
125125
ChannelWrap* channel;
126126
ares_socket_t sock;
127127
uv_poll_t poll_watcher;
128+
129+
void MemoryInfo(MemoryTracker* tracker) const override;
128130
};
129131

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

170-
size_t self_size() const override { return sizeof(*this); }
172+
void MemoryInfo(MemoryTracker* tracker) const override {
173+
tracker->TrackThis(this);
174+
if (timer_handle_ != nullptr)
175+
tracker->TrackFieldWithSize("timer handle", sizeof(*timer_handle_));
176+
tracker->TrackField("task list", task_list_);
177+
}
171178

172179
static void AresTimeout(uv_timer_t* handle);
173180

@@ -181,6 +188,11 @@ class ChannelWrap : public AsyncWrap {
181188
node_ares_task_list task_list_;
182189
};
183190

191+
void node_ares_task::MemoryInfo(MemoryTracker* tracker) const {
192+
tracker->TrackThis(this);
193+
tracker->TrackField("channel", channel);
194+
}
195+
184196
ChannelWrap::ChannelWrap(Environment* env,
185197
Local<Object> object)
186198
: AsyncWrap(env, object, PROVIDER_DNSCHANNEL),
@@ -209,7 +221,10 @@ class GetAddrInfoReqWrap : public ReqWrap<uv_getaddrinfo_t> {
209221
Local<Object> req_wrap_obj,
210222
bool verbatim);
211223

212-
size_t self_size() const override { return sizeof(*this); }
224+
void MemoryInfo(MemoryTracker* tracker) const override {
225+
tracker->TrackThis(this);
226+
}
227+
213228
bool verbatim() const { return verbatim_; }
214229

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

231-
size_t self_size() const override { return sizeof(*this); }
246+
void MemoryInfo(MemoryTracker* tracker) const override {
247+
tracker->TrackThis(this);
248+
}
232249
};
233250

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

271288
void ares_poll_close_cb(uv_poll_t* watcher) {
272289
node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
273-
free(task);
290+
delete task;
274291
}
275292

276293

277294
/* Allocates and returns a new node_ares_task */
278295
node_ares_task* ares_task_create(ChannelWrap* channel, ares_socket_t sock) {
279-
auto task = node::UncheckedMalloc<node_ares_task>(1);
296+
auto task = new node_ares_task();
280297

281298
if (task == nullptr) {
282299
/* Out of memory. */
@@ -1172,7 +1189,9 @@ class QueryAnyWrap: public QueryWrap {
11721189
return 0;
11731190
}
11741191

1175-
size_t self_size() const override { return sizeof(*this); }
1192+
void MemoryInfo(MemoryTracker* tracker) const override {
1193+
tracker->TrackThis(this);
1194+
}
11761195

11771196
protected:
11781197
void Parse(unsigned char* buf, int len) override {
@@ -1349,7 +1368,9 @@ class QueryAWrap: public QueryWrap {
13491368
return 0;
13501369
}
13511370

1352-
size_t self_size() const override { return sizeof(*this); }
1371+
void MemoryInfo(MemoryTracker* tracker) const override {
1372+
tracker->TrackThis(this);
1373+
}
13531374

13541375
protected:
13551376
void Parse(unsigned char* buf, int len) override {
@@ -1393,7 +1414,9 @@ class QueryAaaaWrap: public QueryWrap {
13931414
return 0;
13941415
}
13951416

1396-
size_t self_size() const override { return sizeof(*this); }
1417+
void MemoryInfo(MemoryTracker* tracker) const override {
1418+
tracker->TrackThis(this);
1419+
}
13971420

13981421
protected:
13991422
void Parse(unsigned char* buf, int len) override {
@@ -1437,7 +1460,9 @@ class QueryCnameWrap: public QueryWrap {
14371460
return 0;
14381461
}
14391462

1440-
size_t self_size() const override { return sizeof(*this); }
1463+
void MemoryInfo(MemoryTracker* tracker) const override {
1464+
tracker->TrackThis(this);
1465+
}
14411466

14421467
protected:
14431468
void Parse(unsigned char* buf, int len) override {
@@ -1468,7 +1493,9 @@ class QueryMxWrap: public QueryWrap {
14681493
return 0;
14691494
}
14701495

1471-
size_t self_size() const override { return sizeof(*this); }
1496+
void MemoryInfo(MemoryTracker* tracker) const override {
1497+
tracker->TrackThis(this);
1498+
}
14721499

14731500
protected:
14741501
void Parse(unsigned char* buf, int len) override {
@@ -1499,7 +1526,9 @@ class QueryNsWrap: public QueryWrap {
14991526
return 0;
15001527
}
15011528

1502-
size_t self_size() const override { return sizeof(*this); }
1529+
void MemoryInfo(MemoryTracker* tracker) const override {
1530+
tracker->TrackThis(this);
1531+
}
15031532

15041533
protected:
15051534
void Parse(unsigned char* buf, int len) override {
@@ -1530,7 +1559,9 @@ class QueryTxtWrap: public QueryWrap {
15301559
return 0;
15311560
}
15321561

1533-
size_t self_size() const override { return sizeof(*this); }
1562+
void MemoryInfo(MemoryTracker* tracker) const override {
1563+
tracker->TrackThis(this);
1564+
}
15341565

15351566
protected:
15361567
void Parse(unsigned char* buf, int len) override {
@@ -1560,7 +1591,9 @@ class QuerySrvWrap: public QueryWrap {
15601591
return 0;
15611592
}
15621593

1563-
size_t self_size() const override { return sizeof(*this); }
1594+
void MemoryInfo(MemoryTracker* tracker) const override {
1595+
tracker->TrackThis(this);
1596+
}
15641597

15651598
protected:
15661599
void Parse(unsigned char* buf, int len) override {
@@ -1589,7 +1622,9 @@ class QueryPtrWrap: public QueryWrap {
15891622
return 0;
15901623
}
15911624

1592-
size_t self_size() const override { return sizeof(*this); }
1625+
void MemoryInfo(MemoryTracker* tracker) const override {
1626+
tracker->TrackThis(this);
1627+
}
15931628

15941629
protected:
15951630
void Parse(unsigned char* buf, int len) override {
@@ -1620,7 +1655,9 @@ class QueryNaptrWrap: public QueryWrap {
16201655
return 0;
16211656
}
16221657

1623-
size_t self_size() const override { return sizeof(*this); }
1658+
void MemoryInfo(MemoryTracker* tracker) const override {
1659+
tracker->TrackThis(this);
1660+
}
16241661

16251662
protected:
16261663
void Parse(unsigned char* buf, int len) override {
@@ -1650,7 +1687,9 @@ class QuerySoaWrap: public QueryWrap {
16501687
return 0;
16511688
}
16521689

1653-
size_t self_size() const override { return sizeof(*this); }
1690+
void MemoryInfo(MemoryTracker* tracker) const override {
1691+
tracker->TrackThis(this);
1692+
}
16541693

16551694
protected:
16561695
void Parse(unsigned char* buf, int len) override {
@@ -1729,7 +1768,9 @@ class GetHostByAddrWrap: public QueryWrap {
17291768
return 0;
17301769
}
17311770

1732-
size_t self_size() const override { return sizeof(*this); }
1771+
void MemoryInfo(MemoryTracker* tracker) const override {
1772+
tracker->TrackThis(this);
1773+
}
17331774

17341775
protected:
17351776
void Parse(struct hostent* host) override {

src/connect_wrap.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ class ConnectWrap : public ReqWrap<uv_connect_t> {
1616
v8::Local<v8::Object> req_wrap_obj,
1717
AsyncWrap::ProviderType provider);
1818

19-
size_t self_size() const override { return sizeof(*this); }
19+
void MemoryInfo(MemoryTracker* tracker) const override {
20+
tracker->TrackThis(this);
21+
}
2022
};
2123

2224
} // namespace node

src/env.cc

+14
Original file line numberDiff line numberDiff line change
@@ -653,4 +653,18 @@ void Environment::stop_sub_worker_contexts() {
653653
}
654654
}
655655

656+
// Not really any better place than env.cc at this moment.
657+
void BaseObject::DeleteMe(void* data) {
658+
BaseObject* self = static_cast<BaseObject*>(data);
659+
delete self;
660+
}
661+
662+
Local<Object> BaseObject::WrappedObject() const {
663+
return object();
664+
}
665+
666+
bool BaseObject::IsRootNode() const {
667+
return !persistent_handle_.IsWeak();
668+
}
669+
656670
} // namespace node

src/fs_event_wrap.cc

+4-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@ class FSEventWrap: public HandleWrap {
5656
static void New(const FunctionCallbackInfo<Value>& args);
5757
static void Start(const FunctionCallbackInfo<Value>& args);
5858
static void GetInitialized(const FunctionCallbackInfo<Value>& args);
59-
size_t self_size() const override { return sizeof(*this); }
59+
60+
void MemoryInfo(MemoryTracker* tracker) const override {
61+
tracker->TrackThis(this);
62+
}
6063

6164
private:
6265
static const encoding kDefaultEncoding = UTF8;

0 commit comments

Comments
 (0)