This project is archived and is in readonly mode.

#896 ✓invalid
Neil Jenkins

Equals without type conversion is more efficient

Reported by Neil Jenkins | April 28th, 2010 @ 11:00 PM | in 1.3.0 rc2 (closed)

A lot of code in MooTools uses != or ==, however, these perform type conversion and are less efficient than === and !==. In almost all use cases, the latter could be substituted for the former and perform the desired effect more efficiently. Suggestion: replace all != and == with !== and ===. Where necessary change the function to make it still fit the spec (this is more readable than relying on the type conversion of the current functions).

Comments and changes to this ticket

  • Fábio M. Costa

    Fábio M. Costa April 29th, 2010 @ 02:23 AM

    • Milestone set to 1.3.0 rc2
    • State changed from “new” to “open”

    We understand that === should be faster than ==, but we made benchmarks before and cant see any real difference. DO you have a link showing some interesting results? If it's faster we can change it.

  • Neil Jenkins

    Neil Jenkins April 29th, 2010 @ 08:51 AM

    Sure, try running this test case:

    var x = ['a string', null, undefined, 0, 1000, NaN, false, true, {}, {test: 'object'}, [], [1,2,3] ],
        i, t;
    for (i = 16; i--; ) {
        x = x.concat(x);
    }
    // Array now 786432 elements long.
    t = new Date();
    i = x.length;
    while ( i-- ) {
        var ob = x[i];
        o != null;
        o != undefined;
        o == 'a string';
        o == 'test'
        o == 0;
        o == false;
    }
    var z = [];
    console.log(new Date() - t);
    
    t = new Date();
    i = x.length;
    while ( i-- ) {
        var o = x[i];
        o !== null;
        o !== undefined;
        o === 'a string';
        o === 'test'
        o === 0;
        o === false;
    }
    console.log(new Date() - t);
    

    This tests a variety of different object type comparisons iterated a large number of times to get meaningful results. On my machine, the second version (with the ===) is over twice as fast on Firefox 3.6, about 25% faster on Safari 4 and marginally (1 or 2%) faster on Opera 10.5.

    However, the real benefit is I think == and != can easily mask bugs in the code as the type conversion can cause unintuitive results; using === and !== makes the code a lot clearer.

  • Neil Jenkins
  • Sebastian Markbåge

    Sebastian Markbåge April 29th, 2010 @ 05:01 PM

    • State changed from “open” to “invalid”

    You're not benchmarking the same thing. The outcome of the two operations are different, therefore they're not comparable.

    If you compare Strings with Strings and Numbers with Numbers there should be no performance difference whether you use === or ==.

    The fact that a function can accept objects of a different type is a nice feature of JavaScript. In my personal opinion, type coercion is a good part of JavaScript. For example, no MooTools APIs differentiate undefined and null which makes it easier to use in many cases.

    
    function someMethod(value){
      if (value == null) ... else ...
    }
    
    someMethod(obj.x);
    

    Thanks to type coercion I don't need to care if obj.x is undefined or null.

    Now, if there are actual bugs in MooTools that result from this practice, please post a separate ticket for those bugs so we can fix those.

    If there are performance issues, then it's because the user hasn't converted to the right type already. So, it would already be a bug. If you used === it would be exposed and needed to be fixed.

    So, either we provide the convenience of type coercion or we make it more rigid to help expose performance issues or bugs in poor user code. I'm leaning towards the former. IMO, convenience over rigidity is one of the hallmarks of dynamic languages.

  • Neil Jenkins

    Neil Jenkins April 29th, 2010 @ 11:11 PM

    "If you compare Strings with Strings ... there should be no performance difference."

    This is simply not true. Test Case (http://nmjenkins.com/code/equalstest2.html).

    This is very similar to the test case above but only looks at string comparison. Most occurrences of the == and != operators in MooTools do this (e.g. typeof item != 'string'). I still see the same performance results as before: Firefox is over twice as fast with ===, Safari at least 25% faster. And it's obvious why; the == operator does extra work:

    1. null and undefined are equal
    2. if a number is compared to a string, the string is converted to a number, and the comparison is done again
    3. true is converted to 1, false to 0
    4. if an object is compared to a number or string, the object is converted to primitive, either by calling its valueOf() or toString() method.

    I agree that in the specific case of testing for null or undefined, the use of item == null is shorter, neater and probably more efficient than ( item === null || item === undefined ), however in every other use case the === is more efficient and normally more correct; steps 2, 3 and 4 are unlikely to ever be the desired consequence. This change in no way reduces the flexibility of Mootools, it just makes it very slightly more efficient and less likely to accidentally introduce bugs.

  • Sebastian Markbåge

    Sebastian Markbåge April 30th, 2010 @ 12:13 AM

    You seem to hit some lazy initialization issue in your benchmarks. If you rerun the tests after each other you can cancel out any ordering issues. (You also have an extra array instantiated in the first time span.)

    If you control for these issues I'm not seeing a difference in IE and Chrome. Safari (Win) is SLOWER with ===. You seem to be right about Firefox 3.6 though. Firefox is consistently showing slower values for ==.

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

Shared Ticket Bins

Tags

Pages