number of operations when calculating number of digits in a number is in 2millions, while on crhome its in 60millions

RESOLVED INVALID

Status

()

RESOLVED INVALID
4 years ago
4 years ago

People

(Reporter: noitidart, Unassigned)

Tracking

({perf, testcase})

33 Branch
perf, testcase
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

4 years ago
User Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0
Build ID: 20141002185629

Steps to reproduce:

Tried to figure out how many digits are in a number. This jsperf was created: http://jsperf.com/number-of-digits-in-number


Actual results:

Firefox on Weinsteinn math method is 2mil, while in chrome its 60mil. 

http://i.imgur.com/TgzaFGd.png


Expected results:

Js performance should be better than google chromes

Updated

4 years ago
Status: UNCONFIRMED → NEW
Component: Untriaged → JavaScript Engine
Ever confirmed: true
Keywords: perf, testcase
OS: Windows 8.1 → All
Product: Firefox → Core
Hardware: x86_64 → All
This is why people shouldn't use jsperf for performance measurement.  :(

You never do anything with the value, so the computation can be eliminated as dead code.  Chrome is doing that with some (or all; the numbers I get in a V8 shell locally are quite different from the numbers I get in jsperf) parts of the computation, as far as I can tell.

If I change the testcase to make the code not dead, we seem to be faster than Chrome on it.
(Reporter)

Comment 2

4 years ago
Ah thanks for that insight Boris. 

But how come chrome hits 60mil only in one of the tests while in the other two it hits 8mil

The 8mil tests seem to no be doing anything with the value either. If they were not, then all 3 should hit 60mil no?
Dead-code elimination of function calls is not magic.  You have to know that the function has no side-effects.  That requires either self-hosting the function, inlining it, and then analyzing, or hardcoding which functions are side-effect-free.

Looks like V8 can't dead-code eliminate a toString call on a number.  That's not terribly surprising, since you can only do that if you add special guards about it not being overridden and they might not care too much about that use case.

Also looks like they didn't bother optimizing Math.ceil.  If I use Math.floor instead of Math.ceil, things get dead-code-eliminated in Chrome.
(Reporter)

Comment 4

4 years ago
Thanks Boris this is interesting stuff. So if things are getting dead coded in the 60mil specimen for chrome, how come the equivlent specimen in ff isnt dead coded and also at 60mil or better?
Because we happen to not do dead-code elimination for those functions.  In practice, it's not that common for scripts to have dead code doing math operations, so we haven't really optimized for that case.
(Reporter)

Comment 6

4 years ago
Ah so cool thanks for the info when it didn't real solve anything other than my curiosity.
Thanks man!

Updated

4 years ago
Status: NEW → RESOLVED
Last Resolved: 4 years ago
Resolution: --- → INVALID
Ion can DCE Math functions, but the problem is that the Mul here has a resume point, blocking DCE:

    for (var i=0; i < numbers.length; i++)
        (Math.log(Math.abs(numbers[i] + 1)) * 0.43429448190325176 | 0) + 1

Ion eliminates the "Mul + 1" and then can't eliminate the Mul itself. It *does* turn the Mul into a recover instruction, but unfortunately it can't do that for Math.log yet because we don't have a recover instruction for MMathFunction(Log) atm.

So we need recover instructions for MMathFunction(Log), MToDouble and MLoadElement.

Updated

4 years ago
Component: JavaScript Engine → JavaScript Engine: JIT

Updated

4 years ago
Flags: needinfo?(nicolas.b.pierron)
Depends on: 1092547
Depends on: 1062888
(In reply to Jan de Mooij [:jandem] from comment #7)
> So we need recover instructions for MMathFunction(Log), MToDouble and
> MLoadElement.

MLoadElement cannot be handled as other DCE-d Recover Instruction at the moment, as we need to pay attention to the MStoreElement which might alias the current load.  These instructions are highly dependent on the context in which they are used.

function rloadelem(i) {
    var x = arr[i]; /* true */
    arr[i] = false;
    if (uceFault_loadelem(i) || uceFault_loadelem(i))
        assertEq(x, true);
    return i;
}
Flags: needinfo?(nicolas.b.pierron)
FWIW, we now eliminate both the pure math and weinsteinn math versions, achieving 112m iterations for both. (Because our empty loop performance is second to none, yay us!)
(Reporter)

Comment 10

4 years ago
Hahaha woohoo! :D
You need to log in before you can comment on or make changes to this bug.