Stephen Watkins
Stephen Watkins

Reputation: 25765

Why is this code's execution speed so different?

In Internet Explorer 7, this code executes consistently in 47 ms:

function updateObjectValues() {    
    $('.objects').html(12345678); // ~500 DIVs
}

however, this code executes consistently in 157 ms:

function updateObjectValues() {
    $('.objects').html('12345678'); // ~500 DIVs
}

Passing a number is over 3x faster than a string. Why are these results so dramatically different? And, is there any way to help the performance of the string?

Upvotes: 3

Views: 281

Answers (4)

NickFitz
NickFitz

Reputation: 35021

As T.J. Crowder points out, a look at the source reveals that the code path is quite different for a string; ironically, the associated comment suggests that this is in an attempt to exploit a "shortcut":

html: function( value ) {
        if ( value === undefined ) {
            return this[0] && this[0].nodeType === 1 ?
                this[0].innerHTML.replace(rinlinejQuery, "") :
                null;

        // See if we can take a shortcut and just use innerHTML
        } else if ( typeof value === "string" && !rnocache.test( value ) &&
            (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
            !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {

            value = value.replace(rxhtmlTag, "<$1></$2>");

            try {
                for ( var i = 0, l = this.length; i < l; i++ ) {
                    // Remove element nodes and prevent memory leaks
                    if ( this[i].nodeType === 1 ) {
                        jQuery.cleanData( this[i].getElementsByTagName("*") );
                        this[i].innerHTML = value;
                    }
                }

            // If using innerHTML throws an exception, use the fallback method
            } catch(e) {
                this.empty().append( value );
            }

        } else if ( jQuery.isFunction( value ) ) {
            this.each(function(i){
                var self = jQuery( this );

                self.html( value.call(this, i, self.html()) );
            });

        } else {
            this.empty().append( value );
        }

        return this;
    },

Upvotes: 1

T.J. Crowder
T.J. Crowder

Reputation: 1073968

If you look at the jQuery source code (or even the unminified production version), you'll see that the if (typeof value === "string" ... branch of the code is significantly more complex than the final else version that will occur when you pass in a number.

Here's the 1.4.4 code for if the value is a string:

} else if ( typeof value === "string" && !rnocache.test( value ) &&
    (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
    !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {

    value = value.replace(rxhtmlTag, "<$1></$2>");

    try {
        for ( var i = 0, l = this.length; i < l; i++ ) {
            // Remove element nodes and prevent memory leaks
            if ( this[i].nodeType === 1 ) {
                jQuery.cleanData( this[i].getElementsByTagName("*") );
                this[i].innerHTML = value;
            }
        }

    // If using innerHTML throws an exception, use the fallback method
    } catch(e) {
        this.empty().append( value );
    }
}

Here's what it does with a number:

} else {
    this.empty().append( value );
}

Clearly, the overhead of all those additional checks and function calls add up. I mean, even just in the if statement at the top, there are three regular expression tests, a map lookup, and a string being made lower case — and that's before we get into the body of the statement (if we do, perhaps one of the checks returns false), which involves a further regex (as part of a parameterized replace) and a loop...

Upvotes: 9

Martin Jespersen
Martin Jespersen

Reputation: 26183

I just ran a test and it seemed to confirm my original notion:

.text(string) is as fast as .html(number) ergo there must be string parsing overhead in .html(string)

Whether this overhead is in ie7 or in jQuery is not clear to me. Ie8 doesn't seem to have the same problem, which would suggest that the problem is not i jQuery, but then ie8 has a much faster js engine than ie7...

Upvotes: 3

foo
foo

Reputation: 2111

Numbers can be stored binary, possibly in a single register. Strings have to be stored as, well, a string, in memory. So an optimizing interpreter or JIT-compiler will take advantage of the possible speed an integer provides.

Also, as Martin Jespersen points out, the html() function may handle strings differently than numbers, performing more work on it - if it is aware of the differences. Kudos to Martin there.

Upvotes: 2

Related Questions