FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
node/src/memory_tracker.h at node_process_errors · jasnell/node · GitHub
jasnell
/
node
Public
forked from
nodejs/node
Notifications
You must be signed in to change notification settings
Fork
6
Star
11
Code
Pull requests
0
Actions
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Security and quality
Insights
Expand file tree
Breadcrumbs
node
/
src
/
memory_tracker.h
Copy path
More file actions
More file actions
Latest commit
History
History
History
284 lines (254 loc) · 11.6 KB
Breadcrumbs
node
/
src
/
memory_tracker.h
Copy path
File metadata and controls
284 lines (254 loc) · 11.6 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
#
pragma
once
#
if
defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#
include
"
aliased_buffer.h
"
#
include
"
v8-profiler.h
"
#
include
<
uv.h
>
#
include
<
limits
>
#
include
<
queue
>
#
include
<
stack
>
#
include
<
string
>
#
include
<
unordered_map
>
namespace
node
{
//
Set the node name of a MemoryRetainer to klass
#
define
SET_MEMORY_INFO_NAME
(
Klass
) \
inline
std::string
MemoryInfoName
()
const
override
{
return
#Klass; }
//
Set the self size of a MemoryRetainer to the stack-allocated size of a
//
certain class
#
define
SET_SELF_SIZE
(
Klass
) \
inline
size_t
SelfSize
()
const
override
{
return
sizeof
(Klass); }
//
Used when there is no additional fields to track
#
define
SET_NO_MEMORY_INFO
() \
inline
void
MemoryInfo
(node::MemoryTracker* tracker)
const
override
{}
class
MemoryTracker
;
class
MemoryRetainerNode
;
template
<
typename
T,
bool
kIsWeak
>
class
BaseObjectPtrImpl
;
namespace
crypto
{
class
NodeBIO
;
}
class
CleanupHookCallback
;
/*
Example:
*
* class ExampleRetainer : public MemoryRetainer {
* public:
* // Or use SET_NO_MEMORY_INFO() when there is no additional fields
* // to track.
* void MemoryInfo(MemoryTracker* tracker) const override {
* // Node name and size comes from the MemoryInfoName and SelfSize of
* // AnotherRetainerClass
* tracker->TrackField("another_retainer", another_retainer_);
*
* // Add non_pointer_retainer as a separate node into the graph
* // and track its memory information recursively.
* // Note that we need to make sure its size is not accounted in
* // ExampleRetainer::SelfSize().
* tracker->TrackField("non_pointer_retainer", &non_pointer_retainer_);
*
* // Specify node name and size explicitly
* tracker->TrackFieldWithSize("internal_member",
* internal_member_.size(),
* "InternalClass");
* // Node name falls back to the edge name,
* // elements in the container appear as grandchildren nodes
* tracker->TrackField("vector", vector_);
* // Node name and size come from the JS object
* tracker->TrackField("target", target_);
* }
*
* // Or use SET_MEMORY_INFO_NAME(ExampleRetainer)
* std::string MemoryInfoName() const override {
* return "ExampleRetainer";
* }
*
* // Classes that only want to return its sizeof() value can use the
* // SET_SELF_SIZE(Class) macro instead.
* size_t SelfSize() const override {
* // We need to exclude the size of non_pointer_retainer so that
* // we can track it separately in ExampleRetainer::MemoryInfo().
* return sizeof(ExampleRetainer) - sizeof(NonPointerRetainerClass);
* }
*
* // Note: no need to implement these two methods when implementing
* // a BaseObject or an AsyncWrap class
* bool IsRootNode() const override { return !wrapped_.IsWeak(); }
* v8::Local<v8::Object> WrappedObject() const override {
* return node::PersistentToLocal::Default(wrapped_);
* }
*
* private:
* AnotherRetainerClass* another_retainer_;
* NonPointerRetainerClass non_pointer_retainer;
* InternalClass internal_member_;
* std::vector<uv_async_t> vector_;
* v8::Global<Object> target_;
*
* v8::Global<Object> wrapped_;
* }
*
* This creates the following graph:
* Node / ExampleRetainer
* |> another_retainer :: Node / AnotherRetainerClass
* |> internal_member :: Node / InternalClass
* |> vector :: Node / vector (elements will be grandchildren)
* |> [1] :: Node / uv_async_t (uv_async_t has predefined names)
* |> [2] :: Node / uv_async_t
* |> ...
* |> target :: TargetClass (JS class name of the target object)
* |> wrapped :: WrappedClass (JS class name of the wrapped object)
* |> wrapper :: Node / ExampleRetainer (back reference)
*/
class
MemoryRetainer
{
public:
virtual
~MemoryRetainer
() =
default
;
//
Subclasses should implement these methods to provide information
//
for the V8 heap snapshot generator.
//
The MemoryInfo() method is assumed to be called within a context
//
where all the edges start from the node of the current retainer,
//
and point to the nodes as specified by tracker->Track* calls.
virtual
void
MemoryInfo
(MemoryTracker* tracker)
const
= 0;
virtual
std::string
MemoryInfoName
()
const
= 0;
virtual
size_t
SelfSize
()
const
= 0;
virtual
v8::Local<v8::Object>
WrappedObject
()
const
{
return
v8::Local<v8::Object>();
}
virtual
bool
IsRootNode
()
const
{
return
false
; }
};
class
MemoryTracker
{
public:
//
Used to specify node name and size explicitly
inline
void
TrackFieldWithSize
(
const
char
* edge_name,
size_t
size,
const
char
* node_name =
nullptr
);
inline
void
TrackInlineFieldWithSize
(
const
char
* edge_name,
size_t
size,
const
char
* node_name =
nullptr
);
//
Shortcut to extract the underlying object out of the smart pointer
template
<
typename
T,
typename
D>
inline
void
TrackField
(
const
char
* edge_name,
const
std::unique_ptr<T, D>& value,
const
char
* node_name =
nullptr
);
template
<
typename
T>
inline
void
TrackField
(
const
char
* edge_name,
const
std::shared_ptr<T>& value,
const
char
* node_name =
nullptr
);
template
<
typename
T,
bool
kIsWeak
>
void
TrackField
(
const
char
* edge_name,
const
BaseObjectPtrImpl<T,
kIsWeak
>& value,
const
char
* node_name =
nullptr
);
//
For containers, the elements will be graphed as grandchildren nodes
//
if the container is not empty.
//
By default, we assume the parent count the stack size of the container
//
into its SelfSize so that will be subtracted from the parent size when we
//
spin off a new node for the container.
//
TODO(joyeecheung): use RTTI to retrieve the class name at runtime?
template
<
typename
T,
typename
Iterator =
typename
T::const_iterator>
inline
void
TrackField
(
const
char
* edge_name,
const
T& value,
const
char
* node_name =
nullptr
,
const
char
* element_name =
nullptr
,
bool
subtract_from_self =
true
);
template
<
typename
T>
inline
void
TrackField
(
const
char
* edge_name,
const
std::queue<T>& value,
const
char
* node_name =
nullptr
,
const
char
* element_name =
nullptr
);
template
<
typename
T,
typename
U>
inline
void
TrackField
(
const
char
* edge_name,
const
std::pair<T, U>& value,
const
char
* node_name =
nullptr
);
//
For the following types, node_name will be ignored and predefined names
//
will be used instead. They are only in the signature for template
//
expansion.
inline
void
TrackField
(
const
char
* edge_name,
const
MemoryRetainer& value,
const
char
* node_name =
nullptr
);
inline
void
TrackField
(
const
char
* edge_name,
const
MemoryRetainer* value,
const
char
* node_name =
nullptr
);
template
<
typename
T>
inline
void
TrackField
(
const
char
* edge_name,
const
std::basic_string<T>& value,
const
char
* node_name =
nullptr
);
template
<
typename
T,
typename
test_for_number =
typename
std::
enable_if<std::numeric_limits<T>::is_specialized,
bool
>::type,
typename
dummy =
bool
>
inline
void
TrackField
(
const
char
* edge_name,
const
T& value,
const
char
* node_name =
nullptr
);
template
<
typename
T>
void
TrackField
(
const
char
* edge_name,
const
v8::Eternal<T>& value,
const
char
* node_name);
template
<
typename
T>
inline
void
TrackField
(
const
char
* edge_name,
const
v8::PersistentBase<T>& value,
const
char
* node_name =
nullptr
);
template
<
typename
T>
inline
void
TrackField
(
const
char
* edge_name,
const
v8::Local<T>& value,
const
char
* node_name =
nullptr
);
template
<
typename
T>
inline
void
TrackField
(
const
char
* edge_name,
const
MallocedBuffer<T>& value,
const
char
* node_name =
nullptr
);
inline
void
TrackField
(
const
char
* edge_name,
const
v8::BackingStore* value,
const
char
* node_name =
nullptr
);
inline
void
TrackField
(
const
char
* edge_name,
const
uv_buf_t
& value,
const
char
* node_name =
nullptr
);
inline
void
TrackField
(
const
char
* edge_name,
const
uv_timer_t
& value,
const
char
* node_name =
nullptr
);
inline
void
TrackField
(
const
char
* edge_name,
const
uv_async_t
& value,
const
char
* node_name =
nullptr
);
inline
void
TrackInlineField
(
const
char
* edge_name,
const
uv_async_t
& value,
const
char
* node_name =
nullptr
);
template
<
class
NativeT
,
class
V8T
>
inline
void
TrackField
(
const
char
* edge_name,
const
AliasedBufferBase<NativeT,
V8T
>& value,
const
char
* node_name =
nullptr
);
//
Put a memory container into the graph, create an edge from
//
the current node if there is one on the stack.
inline
void
Track
(
const
MemoryRetainer* retainer,
const
char
* edge_name =
nullptr
);
//
Useful for parents that do not wish to perform manual
//
adjustments to its `SelfSize()` when embedding retainer
//
objects inline.
//
Put a memory container into the graph, create an edge from
//
the current node if there is one on the stack - there should
//
be one, of the container object which the current field is part of.
//
Reduce the size of memory from the container so as to avoid
//
duplication in accounting.
inline
void
TrackInlineField
(
const
MemoryRetainer* retainer,
const
char
* edge_name =
nullptr
);
inline
v8::EmbedderGraph*
graph
() {
return
graph_; }
inline
v8::Isolate*
isolate
() {
return
isolate_; }
inline
explicit
MemoryTracker
(v8::Isolate* isolate,
v8::EmbedderGraph* graph)
: isolate_(isolate), graph_(graph) {}
private:
typedef
std::unordered_map<
const
MemoryRetainer*, MemoryRetainerNode*>
NodeMap;
inline
MemoryRetainerNode*
CurrentNode
()
const
;
inline
MemoryRetainerNode*
AddNode
(
const
MemoryRetainer* retainer,
const
char
* edge_name =
nullptr
);
inline
MemoryRetainerNode*
PushNode
(
const
MemoryRetainer* retainer,
const
char
* edge_name =
nullptr
);
inline
MemoryRetainerNode*
AddNode
(
const
char
* node_name,
size_t
size,
const
char
* edge_name =
nullptr
);
inline
MemoryRetainerNode*
PushNode
(
const
char
* node_name,
size_t
size,
const
char
* edge_name =
nullptr
);
inline
void
PopNode
();
v8::Isolate* isolate_;
v8::EmbedderGraph* graph_;
std::stack<MemoryRetainerNode*> node_stack_;
NodeMap seen_;
};
}
//
namespace node
#
endif
//
defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
Back
|
FazBrowse Home
|
New Git URL