While my profiling did show a lot of GC, I don't know when that occurs. It could easily have been once rendering is finished and there's nothing else going on. That's my understanding of how GC is supposed to work...
I don't think the bulk rendering accounts for all the extra stuff in the heap dump. I added the following code to MrSparks's example:
Code:
var Tracker = function() {
Tracker.count++;
};
Tracker.count = 0;
(function() {
var join = Array.prototype.join;
Array.prototype.join = function() {
if (!this.tracker) {
this.tracker = new Tracker();
}
return join.apply(this, arguments);
};
})();
I also added similar code into
XTemplate.applyOut.
What this does is tag each array used for a join operation with a
Tracker class. I can then see those trackers in the heap dump and trace their GC roots.
Thousands of arrays were augmented (it keeps count) but only about 12 trackers made it through to the heap dump. I think all were caught in closures rather than deliberately kept and whilst this does indicate a memory leak it was only 12 relatively small arrays. The biggest culprit was the cache in
Ext.DomQuery.select, which captures the array
fn in the line:
I then turned my attention to the strings. Some of the largest strings were HTML fragments, so I thought I might be on to something there. Turned out they were
html properties on XTemplates. I made a small tweak to XTemplate so that it wiped the
html property after it was compiled. While this did make those strings disappear from my heap dump it really made very little difference in the grand scheme of things.
One other observation I made is that grids keep recreating the same
XTemplate over and over again. The compile times add up. It probably isn't significant compared to some of the other optimizations you're making but I managed to save myself about 5% on grid resize times by adding in a crude cache.