-
Notifications
You must be signed in to change notification settings - Fork 20.6k
Data: avoid using delete on DOM nodes #2479
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Could you add a comment in the source, of why we don't use |
I've added the same comment that was added to jQuery1 but with an additional link to #1664. The second location references the first instead of copying the same comment. |
delete owner[ this.expando ]; | ||
// Webkit & Blink performance suffers when deleting properties | ||
// from DOM nodes, so set to undefined instead | ||
// https://code.google.com/p/chromium/issues/detail?id=378607 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, i get 403 for this link, you don't?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get a 403 as well. It looks like google has made the bug private, maybe due to security issues with the bug?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm weird.
@paulirish could you help us out? Can we add another link or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing can really be done here except remove the bug link. From the description of it given here, it either has a known security issue or they are verifying there isn't one before allowing it to be public again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now this is a speculation, there might be a mistake or issues was moved, or basically anything else, i would like to wait day or two for the @paulirish response
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Paul is on vacation. Surely won't respond within a few days.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I think we can add Support
comment for the Chrome
, if we don't have information on the Safari, we can leave something in manner of "Possibly reproducible on Safari too" and i will open a ticket for it, so we could deal with it later, when jsperf would be up.
Duplicate that comment in manipulation
module too and since this matter was previously discussed already we can safely land it.
Sounds good?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
We need to verify this bug is still relevant, since jsperf is down, which is pretty unfortunate, would you mind putting together a repo with perf test of benchmarkjs? |
@jbedard You can see in #2439 (comment) how I did that for fractional |
Thanks @mzgol I'll give that a shot |
I landed #2480 so this needs to be rebased on latest Note that since I landed 5fe76c6 on @jbedard could you create an issue, similarly to how you created issue #2503 for PR #2480? |
I'd like to land #2526 first as this will change a few things in this PR. |
Sorry for the delay. I've rebased this. Want me to make the tests more like 624d6a8 though? (Currently they assert Here is the perf test I've been running (and other similar tests): <script src="https://code.jquery.com/jquery-git.js"></script>
<script>
var $j = jQuery.noConflict();
</script>
<script src="../dist/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/1.0.0/benchmark.js"></script>
<script>
var TEMPL = document.createElement('div');
for (var i=0; i<100; i++) {
TEMPL.appendChild(document.createElement('div'));
}
function test($) {
var n = TEMPL.cloneNode(true);
document.body.appendChild(n);
for (var i=0, ii=n.childNodes.length; i<ii; i++) {
$.data(n.childNodes[i], "foo", i);
}
$(n).remove();
}
new Benchmark.Suite()
.add('DOM delete', function() {
test($j);
})
.add('DOM assign', function() {
test($);
})
.on('complete', function() {
console.log('Fastest is ' + this.filter('fastest').pluck('name'));
})
.run();
</script> Generally I'm finding the assign case 5-10% faster on Chrome43. This is nothing compared to the original issue with ~Chrome35 where I think it was 500%. The other measurement was memory usage, doing |
@@ -283,10 +283,14 @@ jQuery.extend({ | |||
} | |||
} | |||
} | |||
delete elem[ dataPriv.expando ]; | |||
// Support: Chrome <=35 - 45 | |||
// Assign undefined instead of using delete, see Data#remove |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want the full comment copied here and below? Seemed like a lot to put in 3 places...
Looks like jsperf is back up and the original test (https://jsperf.com/cleandata/4) shows similar results to my snippet above (delete is still slow on chrome). Would be great if someone could test with the latest safari (or maybe the jsperf already has data from the latest safari, but the data isn't loading for me right now...). |
I've created #2530 for this. |
Hm, could you move var p = jQuery(testDOM.cloneNode(true));
p.children().data("test", 123); bit, out of the test run? Also, could you compare these changes with 3.0 alpha? |
We need new nodes for each test run though since the chrome bug only occurs the first time you delete from a node (I think?). Normally you only |
Check it out - http://benchmarkjs.com/docs#prototype_setup |
That confirms what I was saying. The |
Yeah, it does, it also means you can move those instructions out side of the test run, just like it shown in the link i posted |
So create N nodes outside the loop and I'll try to update the jsperf and compare master with vs without this PR, hopefully later today. |
Thank you :-) |
btw this is the response from V8 on the ticket:
|
@markelog I've updated the jsperf to compare this PR vs 3.0 and to only measure @paulirish thanks for the info! That makes me wonder if jquery should also go back to having a single expando per element instead of two... |
@jbedard now we talking, 40%, not some 12%, this is probably not a bottleneck, but worth a few bytes. @paulirish thank you for the info, now we know exactly why v8 is slower from monomorphic point of view that is, jk of course, nevertheless, ff gives same ops/sec for both cases, so i would suggest to implement additional optimizations for this specific case.
I feel that sometimes the more we know about internals of js engines, the more it provokes devs to create a weirder code-paths. Okay, so, given that perf optimization are now could be considered as proven, whereas byte size impact is minimal and that we already do this for the compat, i'd say it safe to land with one more additional review. Will ping @timmywil regardless. |
// Webkit & Blink performance suffers when deleting properties | ||
// from DOM nodes, so set to undefined instead | ||
// https://code.google.com/p/chromium/issues/detail?id=378607 | ||
// https://github.com/jquery/jquery/pull/1664 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to reference the other PR; followup will start with blame
and/or log
anyway.
Other than an extra comment line, looks good to me. |
Removed the extra comment line... |
I've added one additional change: now that we assign undefined instead of using delete the non-node |
So, in compat, we delete the cache property for anything non-node. While this PR aligns behavior for nodes, it changes behavior for non-nodes. I would like to have the same behavior on both branches. |
Updated to align with compat more. I think that means we only need |
Looking good! Thanks @jbedard! |
@jbedard I rebased your commit over latest master (there were major changes in how we use the QUnit interface) and uploaded it as a branch pr/2479; the latest commit is this rebased one. I get one Lines 2698 to 2717 in c9cf250
Would you like to have a look? You can hard-reset your branch to the one I created and work from there. |
I assume that test needs to be updated to do |
@jbedard Ah, you're right. Do you want to do it or should I modify the PR & land? |
You can go ahead if you want, otherwise it will be another 8h or so before I get around to it... |
Awesome, thanks! |
The jQuery3 data changes started doing
delete elem[ expando ]
similar to what jQuery1 originally did (see #1664). jQuery2 previously left the data property on the nodes and never deleted it so this wasn't an issue.#1664 has the originally jQuery1 discussion. Unfortunately jsperf is down right now and the chrome bug seems to be hidden so I'm not sure if it has actually been fixed. But I ran the jsperf a while back and it seemed to still be an issue.