admin管理员组文章数量:1355522
queryObjects
function returns instances of a given prototype.
I want to inspect retainers of those instances. To do that I need to find them in devtools memory snapshot. One of those instances type is "Object", so searching by class type isn't helpful. They are just too many of them.
How can I find that particular instance in a snapshot?
queryObjects
function returns instances of a given prototype.
I want to inspect retainers of those instances. To do that I need to find them in devtools memory snapshot. One of those instances type is "Object", so searching by class type isn't helpful. They are just too many of them.
How can I find that particular instance in a snapshot?
Share Improve this question asked May 26, 2019 at 8:14 szymszym 3,1982 gold badges24 silver badges32 bronze badges3 Answers
Reset to default 5It would be very hard to distinct the plain "Objects" returned by queryObjects
from all of the plain Objects in the heap snapshot
Here's what I've done to "tag" the objects so I can distinct them easily:
- Create a
TaggedItem
class that can be easily found in dev tools - Create a wrapper function to be called in place of
queryObjects
- The wrapper functions saves return values inside a
WeakMap
- the key is the original return value
- the value is a
TaggedItem
- when the original value is no longer retained anywhere - it's automatically garbage collected from the
WeakMap
queryObjects
function queryObjects { /* Implementation */ }
// or process.env.NODE_ENV == 'development'
if (__DEV__) {
export default wrapWithObjectTagging(queryObjects);
}
else {
export default queryObjects;
}
Decorator implementation
function wrapWithObjectTagging(func) {
function withObjectTagging(...args) {
const originalReturnValue = func.apply(this, args);
/* We're using Promise.resolve in case the original function returns a promise */
Promise.resolve(originalReturnValue)
.then((data) => {
// Weak map keys can be objects only
if (typeof data == 'object') {
const tag = new TaggedItem(data);
taggedItems.set(data, tag);
}
});
return originalReturnValue;
}
return withObjectTagging;
}
/**
* Capture tags in a weak map
* When the original object (key) is no longer used anywhere in app - the data (TaggedItem)
* is free for garbage collection and removed
* Using dev tools we see which TaggedItems are still retained and what's using them - preventing GC
* @type {WeakMap<object, TaggedItem>}
*/
const taggedItems = new WeakMap();
/**
* Class instances are easily tracked by Dev tools memory snapshots
* Wrapping a result with such instance allows us to track it without
* incurring extra weight
*/
class TaggedItem {
constructor(data) {
// This ref helps us inspect what is retaining the original data
this.ref = data;
/* This is not really necessary but makes the TaggedItem represent
Retained Memory more accurately */
Object.assign(this, data);
}
}
The TaggedItem
is referencing the original data directly, but since nothing is referencing the TaggedItem
- we never expose it - it does not prevent the WeakMap
from garbage collecting the original data and the TaggedItem
that captured it
Here is a sample of how that works in Chrome Dev Tools:
- Take a Heap Snapshot
- Search for the object class name (TaggedItem)
- Select an item
- See retainers
- We're observing a
TaggedItem
- It's retained by the
report
property of another object, that uses the original data
A simpler approach is to append a key to the original object
Decorating by appending a custom fieldfunction wrapWithObjectTagging(func) {
function withObjectTagging(...args) {
const originalReturnValue = func.apply(this, args);
if (typeof originalReturnValue == 'object') {
originalReturnValue.__tag = new TaggedItem();
}
return originalReturnValue;
}
return withObjectTagging;
}
class TaggedItem {}
This way you can still filter by TaggedItem
in dev tools and see what's retaining the TaggedItem
and in turn the parent object
The first approach gives a better estimate of total retained memory, while the simple approach would just allow you to trace what's retaining the original
Add explicit string property e.g. let o = {type:'myType'}
and then use ctrl
+F
in snapshot.
There retainers are all your o
objects.
If it's ok to modify these objects you can try the following trick.
Store the array you got from the queryObjects into a temp variable. You can do it via the context menu. Then run the following code to give each object a unique id:
temp1.forEach((t, i) => t.__id = String(i))
Then take a heap snapshot. Now each object should be identifiable by that __id string.
本文标签:
版权声明:本文标题:javascript - How to find a particular object in DevTools memory snapshot if the type of the object is just "Object& 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1743948664a2566879.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论