Open
Bug 605486
Opened 14 years ago
Updated 2 years ago
Array manipulation slow in Firefox, fast in Chrome & Opera
Categories
(Core :: JavaScript Engine, defect)
Tracking
()
NEW
Tracking | Status | |
---|---|---|
blocking2.0 | --- | - |
People
(Reporter: paul, Unassigned)
References
(Depends on 1 open bug, )
Details
(Keywords: perf, Whiteboard: [jsperf])
Attachments
(6 files, 1 obsolete file)
This test http://jsperf.com/matrix-test is 3 times faster in Chrome and 2 times faster in Opera.
Result with my computer:
* Firefox 4.0b8pre (20101018): 290,754 (3rd test)
* Opera 10.63: 631,368 (3rd test)
* Chrome 8.0.552.0 dev: 1,011,358 (3rd test)
Comment 1•14 years ago
|
||
Paul, do you understand the scoring setup used by jsperf? Alternately, can you create a version of this test outside their test harness? They have some "calibration" monkey business that makes it very hard to tell what their numbers actually mean; in particular I've had patches that sped up something by 2x have no effect on the score jsperf reports for the same thing.
Comment 2•14 years ago
|
||
Note that a version of the test outside their harness would also make it easier to profile....
Comment 3•14 years ago
|
||
I will do it
Comment 4•14 years ago
|
||
Comment 5•14 years ago
|
||
OK, on the attached test I see these results (on Mac 10.6):
Chrome 8 dev:
nb iteration 1000000
duration matrix0 1919
duration matrix1 792
duration matrix2 648
Opera 10.61:
nb iteration 1000000
duration matrix0 3235
duration matrix1 1569
duration matrix2 701
Current m-c tip:
nb iteration 1000000
duration matrix0 849
duration matrix1 574
duration matrix2 594
However on the same exact builds I can confirm that the jsperf.com test reports much higher numbers in Chrome and Opera.
So what's going on here?
Comment 6•14 years ago
|
||
Oh, there's one obvious difference. The jsperf test is calling makeIdentity() once per iteration, while the attached testcase calls it once and then calls inverse() a bunch of times on it.
Comment 7•14 years ago
|
||
Attachment #484341 -
Attachment is obsolete: true
Comment 8•14 years ago
|
||
With that testcase, I have:
Chrome 8:
duration matrix0 2110
duration matrix1 1053
duration matrix2 899
Opera 10.61:
duration matrix0 4352
duration matrix1 2310
duration matrix2 1222
Minefield:
duration matrix0 1163
duration matrix1 1058
duration matrix2 1250
So now at least we're slower than Chrome on matrix2, presumably because of their better gc. But this _still_ totally doesn't match the jsperf results.
Reporter | ||
Comment 9•14 years ago
|
||
Yes, sounds like jsperf mess up the script. INVALID?
Cedric, anything to add?
Comment 10•14 years ago
|
||
One other thing. For matrix2 for Chrome, say, jsperf reports 984,024 ops/s over here. The timing test above reports 899ms to do 1e6 ops. So that works out to 1,112,347 ops/s as measured locally.
For Minefield, the relevant numbers are 231,740 ops/s on jsperf and 1250ms to do 1e6 ops; the latter works out to 800,000 ops/s. So somehow jsperf's "overhead" for Chrome is order of 10% while for us it's order of 4x.
Can someone figure out exactly how jsperf generates those numbers?
Comment 11•14 years ago
|
||
And to be clear, we've had this stuff (jsperf.com testcases) pasted around a _lot_ recently. So I think we need to either fix whatever makes all jsperf tests slow in our impl or get jsperf fixed if the bug is on their end.
Comment 12•14 years ago
|
||
I sent mail to Mathias (the guy who created jsperf); will see what he says.
Comment 13•14 years ago
|
||
Yes but makeIdentity was the same for all test (so I removed from the test), I
dont know what is going on the jsperf stuff.
I have tried to increase by one 0 the number of iteration and result are really weird:
my numbers:
firefox beta6
nb iteration 1000000
duration matrix0 1096
duration matrix1 1311
duration matrix2 1185
minefield from yesterday
nb iteration 1000000
duration matrix0 5727
duration matrix1 3210
duration matrix2 2467
chromium 8 from yesterday
nb iteration 1000000
duration matrix0 1905
duration matrix1 839
duration matrix2 664
Comment 14•14 years ago
|
||
just to be clear the previous number was posted with 1000000 iterations, I dont know why but my minefield version seems slow. I will check I dont have a config that would have an effect on it
Comment 15•14 years ago
|
||
Here I see:
Chrome 8:
matrix0 445714 runs/s
matrix1 807990 runs/s
matrix2 858009 runs/s
Opera 10.61:
matrix0 231504 runs/s
matrix1 346134 runs/s
matrix2 695549 runs/s
Minefield:
matrix0 770645 runs/s
matrix1 784818 runs/s
matrix2 787869 runs/s
Comment 16•14 years ago
|
||
> I dont know why but my minefield version seems slow.
Do you have Firebug installed?
But again, I see the problem on jsperf on a build that's showing fast numbers with the testcases attached here. So there's a jsperf-related problem no matter what.
Comment 17•14 years ago
|
||
I would prefer to put date code outside the loop test. Could you have a test with the new script and report your number ?
Comment 18•14 years ago
|
||
Yes it was FireBug :)
thank you for the suggestions
Comment 19•14 years ago
|
||
ok here my number with last script:
chromium
nb iteration 1000000
matrix0 Run/s 514933
matrix1 Run/s 1157407
matrix2 Run/s 1477104
minefield
nb iteration 1000000
matrix0 Run/s 1474926
matrix1 Run/s 1650165
matrix2 Run/s 1633986
Comment 20•14 years ago
|
||
> Yes it was FireBug :)
OK... now why? And why did you not realize it? ;) And I assume you still see the jsperf slowness even with firebug off?
See discussion in bug 603426; if you have something that would be useful to add there, please do...
It really sounds like the two remaining issues are jsperf stuff and bug 603426.
Updated•14 years ago
|
Whiteboard: [jsperf]
Comment 21•14 years ago
|
||
Well I gess I trusted too much jsperf :)
Thank you for the discussion, I learnt more about testing preformance with js.
Comment 22•14 years ago
|
||
(In reply to comment #10)
> Can someone figure out exactly how jsperf generates those numbers?
Here’s how: http://github.com/mathiasbynens/benchmark.js/blob/master/benchmark.js#L178-185 Note that the benchmarking script used on jsPerf is based on JSLitmus, so that’s where most of the magic comes from.
For the record, my test results on http://jsperf.com/matrix-test#run are as follows:
Chrome 7.0.517.41 (latest stable release)
matrix0: Looped 163,840 times in 0.6399508125 seconds = 256,020 operations per second
matrix1: Looped 327,680 times in 0.5329508125 seconds = 614,841 operations per second
matrix2: Looped 655,360 times in 0.7509508125 seconds = 872,707 operations per second
Opera 10.63 (latest stable release)
matrix0: Looped 163,840 times in 0.793016 seconds = 206,604 operations per second
matrix1: Looped 163,840 times in 0.668876 seconds = 244,948 operations per second
matrix2: Looped 327,680 times in 0.718876 seconds = 455,823 operations per second
Firefox 3.6.10 (latest stable release)
matrix0: Looped 10,240 times in 0.574079 seconds = 17,837 operations per second
matrix1: Looped 40,960 times in 0.520079 seconds = 78,757 operations per second
matrix2: Looped 81,920 times in 0.890079 seconds = 92,037 operations per second
Firefox 4.0b8pre:
matrix0: Looped 81,920 times in 0.618928625 seconds = 132,358 operations per second
matrix1: Looped 163,840 times in 0.881928625 seconds = 185,775 operations per second
matrix2: Looped 163,840 times in 0.716429 seconds = 228,690 operations per second
That indeed differs from the test latest test case made by Cedric, which gives me the following results for Firefox 4.0b8pre:
nb iteration 1,000,000
matrix0: Run/s 1,388,888
matrix1: Run/s 1,600,000
matrix2: Run/s 1,577,287
To be honest, I have no idea why there’s this much difference. It doesn’t make much sense — jsPerf uses a reverse while loop to run the tests; the non-jsPerf test case uses a for-loop, which is known to be *slower*. Even if for-loops would be faster in Minefield, this might make a tiny difference, but it shouldn’t be this big. Also, the number of iterations is higher in the non-jsPerf test case, which should only add to its accuracy.
If no one spots any major bugs in the benchmark.js source code I linked above, I’ll get in touch with Robert (JSLitmus author / voodoo JS coder).
Comment 23•14 years ago
|
||
I attached a test case using a reverse while loop instead of a for-loop just to be sure — but the results seem to be about the same.
Comment 24•14 years ago
|
||
Chrome 7.0.517.41 (latest stable version):
matrix0: 146,357 ops/sec
matrix1: 145,319 ops/sec
matrix2: 138,442 ops/sec
Firefox 4.0b8pre:
matrix0: 146,619 ops/sec
matrix1: 145,319 ops/sec
matrix2: 144,550 ops/sec
Comment 25•14 years ago
|
||
Interesting. Using the latest attached testcase I see chrome once again scoring much higher than minefield.
Mathias, thanks for the code link; let me go stare at it.
Comment 26•14 years ago
|
||
OK. So I grabbed the code from the comment 24 and ran it locally. I also logged the function f, count and raw runtime in seconds that we're dealing with in _run, before any of the calibrations stuff is taken into account.
I get log output something like this in Minefield:
function () {
inv2 = osg.Matrix2.inverse(i2);
}
163840
0.682
and like this in Chrome:
function () {
inv2 = osg.Matrix2.inverse(i2);
}
655360
0.521
If I try to time that directly, like so:
function g(f, count) {
try {
var start = new Date();
var i = count;
while (i--) f();
alert(new Date() - start);
} catch (e) {
}
}
g(function() {
inv2 = osg.Matrix2.inverse(i2);
}, 163840);
I get 77ms in Minefield and 144ms in Chrome....
Comment 27•14 years ago
|
||
It's definitely something about the way the test ramps up its iteration counts. If I change comment out the two calibration tests and change INIT_COUNT from 10 to 100000, I get totally different numbers in Minefield, but the same ones in Chrome.
Comment 28•14 years ago
|
||
If I disable methodjit, the slowness goes away on the jslitmus testcase.
Looks like for some reason the rampup causes us to blacklist the loop, but only when methodjist is enabled. And JM is slower than V8 on this code. I'll attach a shell testcase demonstrating this problem.
Now... this is true for the jslitmus testcase. On jsperf.com, disabling methodjit leads to a significant slowdown...
Adding a dependency on bug 580468 for the jslitmus issue, but _something_ else is going on with jsperf.com.
blocking2.0: --- → ?
Depends on: 580468
Comment 29•14 years ago
|
||
When run -j -m, the third number printed is much smaller than the first one; the first is about the same as both numbers when run -j, while the third is about the same as both numbers when run -m.
Comment 30•14 years ago
|
||
OK, with the jsperf code, but not with the jslitmus code (?) the calibrations stuff ends up mattering. If I turn off the running of the calibration functions, or even the running of just _one_ of the calibration functions, then things are fast.
Comment 31•14 years ago
|
||
Ah, no. I have to explicitly turn off this part to make things fast:
new Test('Calibrating loop', 'cl', function(count) { while (count--) { } }),
if I leave that in, even if I comment out the other calibration function, things are slow. If I comment it out _and_ disable methodjit (to work around the issue from comment 29), things are fast.
Comment 32•14 years ago
|
||
And the reason for that is:
trace stopped: 8860: can only inc numbers
Abort recording of tree file:///Users/bzbarsky/test.js:179@104 at file:///Users/bzbarsky/test.js:97@5: argdec.
(test.js is the file linked to from comment 22). And in particular, |count| there is undefined.
I get the above three times, which makes sense: that calibration is run over and over. And then we blacklist the loop at like 179. Which is the main benchmark loop.
Comment 33•14 years ago
|
||
So the reason the undefined doesn't happen in the original jslitmus is that their test-runner looks like this:
if (this.loopArg) {
// ... let it do the iteration itself
f(count);
} else {
// ... otherwise do the iteration for it
while (i--) f();
}
while jsbench dropped the if condition... but the while(count--) test above matches the loopArg regexp, so was getting called with an actual argument in jslitmus, but not jsbench.
Of course jsbench also doesn't use the result of the loop calibration.... ;)
Comment 34•14 years ago
|
||
Er, s/jsbench/jsperf/g in comment 33.
Comment 35•14 years ago
|
||
So there are three issues here, I think:
1) Should we attempt to trace inc() on undefined?
2) Why does JM blacklist the loop when ramping up, and will bug 580468 fix that?
3) Why is JM 3x slower than tracer here?
dvander, dmandelin, want me to file those as separate bugs blocking this one?
Comment 36•14 years ago
|
||
(In reply to comment #35)
> 2) Why does JM blacklist the loop when ramping up, and will bug 580468 fix
When running JM+TM in combination, a trace gets blacklisted if it's run for fewer than 8 iterations the first time it executes.
This heuristic is made a little more friendly in bug 580468. We watch the first 10 executions of the trace and blacklist if it executes fewer than 200 total iterations (so an average of 20 per execution). Do you know if this will be sufficient to allow this loop to be traced?
Comment 38•14 years ago
|
||
> When running JM+TM in combination, a trace gets blacklisted if it's run for
> fewer than 8 iterations the first time it executes.
Ah, and in this case ramp-up starts with 10 iterations, so we end up running it on trace for only 2 iterations and blacklisting?
The ramp-up here goes up by powers of 2 starting at 10, so 10 executions will get us way past 200 total iterations.
Comment 39•14 years ago
|
||
js> x = undefined
js> x++
NaN
js> x++
NaN
Not really useful even in a benchmark. Is it intended?
/be
Comment 40•14 years ago
|
||
NO, it's not intended. See comment 33.
Comment 41•14 years ago
|
||
(In reply to comment #40)
> NO, it's not intended. See comment 33.
I had trouble parsing that without reading the code (which I didn't cuz I am a lazy bastard ;-). Thanks, hope the code can be fixed. Mathias, is it all under your control?
/be
Comment 42•14 years ago
|
||
(In reply to comment #41)
> Thanks, hope the code can be fixed. Mathias, is it all under your control?
Yes, it is. I just deployed this change: http://github.com/mathiasbynens/benchmark.js/commit/77696aa7310607b31562b608226b33107c9830ae
That appears to fix the jsPerf/Firefox issues. I’ll see what I can do to reset all the Browserscope results.
Comment 43•14 years ago
|
||
For what it’s worth, I’ve just cleared the Browserscope results for all 2,768 jsPerf test cases.
Comment 44•14 years ago
|
||
I just have a tried on jsperf on my matrix test, and if I run the test many times, I can have very different result. I dont know if it's expected eg:
first run
682,327 8% slower
749,206 fastest
745,796 0% slower
second run
144,736 37% slower
204,037 12% slower
232,730 fastest
third run
137,454 53% slower
208,718 29% slower
295,216 fastest
I used firefox b8 the same version I reported this bug.
Hopes it will help
Comment 45•14 years ago
|
||
Cedric, at this point you're just seeing
Comment 46•14 years ago
|
||
Er, seeing the effects of comment 35 item 2. The first run times there are the ones you should more or less expect in general once that issue is resolved.
Updated•14 years ago
|
blocking2.0: ? → -
Comment 47•12 years ago
|
||
Firefox 17
97,119 ±9.03% 41% slower
160,043 ±7.66% 1% slower
169,675 ±12.45% fastest
Firefox 19 (20121022 Nightly)
67,074 ±2.18% 63% slower
167,460 ±4.96% 9% slower
184,023 ±4.68% fastest
Chrome 22
215,892 ±2.41% 57% slower
491,895 ±1.37% fastest
488,784 ±1.15% 0.41% slower
Comment 48•12 years ago
|
||
Firefox 21
145,575 ±5.32% 46% slower
225,466 ±2.72% 15% slower
269,307 ±4.74% fastest
Great improvement from earlier Ion development (My last reply was showing a regression on the first test).
Assignee | ||
Updated•10 years ago
|
Assignee: general → nobody
Updated•2 years ago
|
Severity: normal → S3
You need to log in
before you can comment on or make changes to this bug.
Description
•