I’ve recently been involved in some memory leak troubleshooting and wanted to note the following caches, which often end up being the culprits retainers of some objects that were not cleaned up (e.g. destroy()) correctly, for one reason or another:
Ext.ComponentManager.all // Ext.Component cache as map
Ext.cache // Ext.Element cache as map
Ext.StoreManager.items // Ext.data.Store cache as array
Ext.fx.Manager.targets.map // Ext.fx.target.Element cache as map
Ext.dd.DragDropManager.ids // DD Object cache as map - also "leaks" by design;
// it retains empty objects mapped out to IDs that
// used to be legit components, so minimal memory
// impact, but those IDs are never wiped |
Ext.ComponentManager.all // Ext.Component cache as map
Ext.cache // Ext.Element cache as map
Ext.StoreManager.items // Ext.data.Store cache as array
Ext.fx.Manager.targets.map // Ext.fx.target.Element cache as map
Ext.dd.DragDropManager.ids // DD Object cache as map - also "leaks" by design;
// it retains empty objects mapped out to IDs that
// used to be legit components, so minimal memory
// impact, but those IDs are never wiped
I also would like to share the following functions that I use to compare snapshots of these caches:
// e.g.
// * var s1 = getCacheSnapshot()
// * ... interact with the app
// * var s2 = getCacheSnapshot()
// * compareCacheSnapshots(s1, s2);
function getCacheSnapshot() {
return {
cmp: Ext.Object.getKeys(Ext.ComponentManager.all),
el: Ext.Object.getKeys(Ext.cache),
st: Ext.Array.pluck(Ext.StoreManager.items, 'storeId'),
fx: Ext.Object.getKeys(Ext.fx.Manager.targets.map),
dd: Ext.Object.getKeys(Ext.dd.DragDropManager.ids)
};
}
// logs any deltas
function compareCacheSnapshots(s1, s2) {
function diffArrays(name, a1, a2) {
var added = Ext.Array.difference(a2, a1);
var removed = Ext.Array.difference(a1, a2);
if (added.length || removed.length) {
console.log(' ---- ', name, 'Added:', added, 'Removed:', removed);
}
}
for (var key in s1) {
var a1 = s1[key];
var a2 = s2[key];
console.log(key, a1.length === a2.length ? a1.length : a1.length + '->' + a2.length);
diffArrays(key, a1, a2);
}
} |
// e.g.
// * var s1 = getCacheSnapshot()
// * ... interact with the app
// * var s2 = getCacheSnapshot()
// * compareCacheSnapshots(s1, s2);
function getCacheSnapshot() {
return {
cmp: Ext.Object.getKeys(Ext.ComponentManager.all),
el: Ext.Object.getKeys(Ext.cache),
st: Ext.Array.pluck(Ext.StoreManager.items, 'storeId'),
fx: Ext.Object.getKeys(Ext.fx.Manager.targets.map),
dd: Ext.Object.getKeys(Ext.dd.DragDropManager.ids)
};
}
// logs any deltas
function compareCacheSnapshots(s1, s2) {
function diffArrays(name, a1, a2) {
var added = Ext.Array.difference(a2, a1);
var removed = Ext.Array.difference(a1, a2);
if (added.length || removed.length) {
console.log(' ---- ', name, 'Added:', added, 'Removed:', removed);
}
}
for (var key in s1) {
var a1 = s1[key];
var a2 = s2[key];
console.log(key, a1.length === a2.length ? a1.length : a1.length + '->' + a2.length);
diffArrays(key, a1, a2);
}
}
VN:F [1.9.22_1171]
Rating: 5.1/10 (18 votes cast)