Reputation: 7960
Background: So, I was trying to do a test to see the performance differences in three approaches to binding a "click" event using jQuery's on.()
. I was seeing some pretty big differences (way bigger than I expected) and when running the results by a colleague, he noticed that, if you switch the order of the test runs, the results changed, but were equally "out of whack".
So, I decided to do a very straightforward test:
1) One parent <div>
containing 100 child <div>
s, each with simply a number inside (1-100) and the class
value "target-element".
2) Each element has a click
event bound to it, using this:
$(".target-element", "#context1").on("click", logClick);
3) The click
event simply sets the text value to a local variable:
function logClick() {
var sTextVal = $(this).text();
}
4) And then, I set up a "trigger" function to call the clicks on all of the child <div>
s:
function triggerClicks(context) {
$(context).find(".target-element").each(function() {
$(this).click();
});
});
5) Then, I set up 3 test runs, that all call the EXACT same test:
Run 1 ---> triggerClicks("#context1");
Run 2 ---> triggerClicks("#context1");
Run 3 ---> triggerClicks("#context1");
You can see the test here: http://jsperf.com/jsperf-perf-test
The results are DRASTICALLY different across all of the browsers that I tested with, continuously getting slower as the runs continue:
Chrome 41
Run 1 ---> 59.91 Ops/sec (±6.55%) - fastest
Run 2 ---> 32.72 Ops/sec (±5.06%) - 45% slower
Run 3 ---> 23.69 Ops/sec (±3.39%) - 59% slower
Firefox 36
Run 1 ---> 52.69 Ops/sec (±10.21%) - fastest
Run 2 ---> 26.70 Ops/sec (±6.38%) - 48% slower
Run 3 ---> 15.95 Ops/sec (±24.55%) - 73% slower
IE 9
Run 1 ---> 26.98 Ops/sec (±14.43%) - fastest
Run 2 ---> 11.77 Ops/sec (±8.89%) - 54% slower
Run 3 ---> 7.54 Ops/sec (±6.85%) - 70% slower
So what am I missing here? I realize that it's a repetitive test and is dealing with a lot of elements, but that should not be affecting the results of the runs that greatly. Can anyone see any reason why this would be happening as a result of my code and NOT something seriously wrong with JSPerf?
Upvotes: 3
Views: 92
Reputation: 33163
If you look at the help text next to the preparation code field in the form:
runs before each clocked test loop, outside of the timed code region
That means the code is run before every test case, not only once. Therefore in the second test case you will have two event handlers attached to each element and three in the third test case.
This is why there's a field for "teardown" right below the preparation field: it's supposed to be used to undo what you've done in the setup to avoid situations like this. If you add this to the teardown:
$(".target-element", "#context1").off("click");
then the existing event handlers are removed before you add new ones and the tests take about the same time to run.
Upvotes: 3