here is a chat box, and then insert chat data in real time, the process is roughly as follows:
// .
function appendMsg () {
var newMsg = "<some-html-string></some-html-string>";
$chatList.append(newMsg); // jQuery Function.
}
then we limit the number of chat boxes to 100 at most:
// , 100 .
function appendMsg () {
var newMsg = "<some-html-string></some-html-string>";
$chatList.children().length > 100 && $chatList.children().first().remove();
$chatList.append(newMsg);
}
looks like OK, but when there are more users (20000 +) and chat areas are frantically brushed up, browser performance will decline significantly. Using Chrome developer tools for analysis, the number of Nodes
in Timeline
increases linearly, but the total memory usage remains within a fixed range. The cliff icon of JS Heap
also indicates that the GC process is normal.
there is a question at this time: $(.). Remove () / removeChild () Why does the Nodes in the developer"s tools still rise and cause a significant decline in browser performance, but the memory is still normally reclaimed after the nodes are removed?
after trying several optimizations, the effect does not improve much. Later, I try to change the operation logic of node restrictions: take out the first chat item node when it exceeds 100. modify the HTML and then put it back to the chat list
. The code is roughly as follows:
// , 100 .
function appendMsg () {
var newMsg = "<some-html-string></some-html-string>";
if ($chatList.children().length > 100) {
var $firstMsg = $chatList.children().first();
$firstMsg.remove().html(newMsg);
$chatList.append($firstMsg);
} else {
$chatList.append(newMsg);
}
}
after using the above strategy, the performance problem disappears, and the Nodes
curve in Timeline in the Chrome developer tool behaves the same as JS Heap
, that is, it will be recycled after a period of time, then rise again, and then be recycled again.
is deeply confused and has a completely different result. Is it because the node of the latter append
is taken from the page instead of a new variable? Is it because the memory of the former is not recycled? But the developer tool indicates that memory has been recycled; is it because the latter"s Nodes
has been correctly recycled? But aren"t both common remove
operations, why is the former soaring? What exactly does this Nodes
stand for? But unfortunately, after searching a lot of content on the explosive stack, we couldn"t find any clear content related to "GC behavior after the removal of Nodes and Dom". Most of them are vague, perhaps because of the wrong posture ("; ; `)
in addition, about this Nodes
:
var parent = document.getElementById("parent");
setInterval(function () {
var div = document.createElement("div");
div.innerHTML = "papapa";
parent.children.length > 100 && parent.removeChild(parent.children[0]);
parent.appendChild(div);
}, 10);
A page with such a simple timer should have 100 nodes, but the number of Nodes
in developer tools remains at 200 + all the time. so what exactly is this Nodes
("_ `)
the writing is quite confusing. If anyone can give me some advice, I would appreciate it. (please)
Update:
has been instructed by two people to take a brief look at the part of the code about remove in jQuery. It may not be understood correctly, and please give me more advice.
remove part of the code is roughly as follows:
jQuery.fn.extend({
//...
remove: function( selector ) {
return remove( this, selector );
}
});
// Remove .
function remove( elem, selector, keepData ) {
var node,
nodes = selector ? jQuery.filter( selector, elem ) : elem,
i = 0;
for ( ; ( node = nodes[ i ] ) != null; iPP ) {
if ( !keepData && node.nodeType === 1 ) {
jQuery.cleanData( getAll( node ) ); // :.
}
if ( node.parentNode ) {
if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
setGlobalEval( getAll( node, "script" ) ); // .
}
node.parentNode.removeChild( node ); // : removeChild .
}
}
return elem; // .
}
// clearData .
cleanData: function( elems ) {
var data, elem, type,
special = jQuery.event.special,
i = 0;
for ( ; ( elem = elems[ i ] ) !== undefined; iPP ) {
if ( acceptData( elem ) ) {
if ( ( data = elem[ dataPriv.expando ] ) ) {
if ( data.events ) {
for ( type in data.events ) {
if ( special[ type ] ) {
jQuery.event.remove( elem, type );
// This is a shortcut to avoid jQuery.event.remove"s overhead
} else {
jQuery.removeEvent( elem, type, data.handle );
}
}
}
// Support: Chrome <= 35-45+
// Assign undefined instead of using delete, see Data-sharpremove
elem[ dataPriv.expando ] = undefined;
}
if ( elem[ dataUser.expando ] ) {
// Support: Chrome <= 35-45+
// Assign undefined instead of using delete, see Data-sharpremove
elem[ dataUser.expando ] = undefined;
}
}
}
}
so it does seem that after calling remove ()
, it only removes the Dom node and clears the Dom information. As for what jQuery does at other stages (such as caching or other behavior), it is indeed possible that the node is not released.
I will take the time to check it again, thank you