htmlEscape vs goog.string.htmlEscape

JavaScript performance comparison

Revision 2 of this test case created by termi

Preparation code

 
<script>
Benchmark.prototype.setup = function() {
    var _rhtml = /[&<>"]/g
    var _rspecial = {
        '&':'&amp;',
        '<':'&lt;',
        '>':'&gt;',
        '"':'&quot;'
    };
   
    function _replaceEntity(a) {
        return _rspecial[a];
    }
   
   
    function htmlEscape(str) {
        if (_rhtml.test(str)) {
                return str.replace(_rhtml, _replaceEntity);
        }
        return str;
    }
   
    function htmlEscape_typeOf(str) {
        if (typeof str === "string") {
                if (_rhtml.test(str)) {
                        return str.replace(_rhtml, _replaceEntity);
                }
        }
        return str;
    }
   
   
    var strings = [
        428
        , 48360487568346873894576078956789346943
        , 5.35235
        , false
        , true
        , null
        , NaN
        , {}
        , []
        , 'safj'
        , 'njsjsdghjksdhgjsdhgjahdjsklghjsklgndjcgdfsgjnhfdsjncfgjsdhcfjlghx'
        , 'basjdgh - & - jdsghjdshgj', 'basjdgh - & < - jdsghjdshgj', 'basjdgh - & <> - jdsghjdshgj'
        , 'basjdgh - & <> " - jdsghjdshgj', '& <> " - jdsghjdshgjdjsgjkah4i7y87937x84xnu <> #^%#&#^7>@<^>@#^^>*^*(><$>!^<>%$&<^$&^*#<#>^@^"!^@#^"@^$M@#>^<#@>^<@#^:<!^><!>#<^$><$!<^><$!#>^<$#>^&<>#@<&>$#*<#%^#!$<>^<:@:<^!:#<&"#%<&@$"&'
        , '"sdj ghjsagjkajskghsajk gsadhg jkshj gsjakg akshg u9482y1t846., 3y3782yzn87393a87 usgjsagahjks g " adgs h gjahsjk gskdhgjk ahsjk gksg ksagagds < 463436 4756 7w678 t678gsagas > 7a67678se6t78678gf678bv6xz78@$ ^ $# ^ * ^ & * & #$ jfgsuhgjkshjk fgsdgasgegadhksgj skagkdgj ksdh jkgksagj ksah gjkaskgksahgjk sj gjksh gjkhasjk gasg S < > sdgjasjy347 6378659 8072827687 59092768 0786 * ^ & * % ^ & % $ ^ & s gasg as., g., .46 "<> A< >$r878784786t748657 aa84678a 290756902467a07a249 64 <>A>#^ A$8a9a684289689389 98 9a3898926'
        , ' 725y832y8924 89q2q49 8978w7ysdjvcvmxbvasugjwakehgsnzjkg ksfg sa"s adgjadhsu gjkdsag sdajk g " sadgjaksguasgiwguiywigsua giqwuirghuiguwy7834t78re78da'
    ];
   
    var goog_string_amperRe_ = /&/g;
    var goog_string_ltRe_ = /</g;
    var goog_string_gtRe_ = />/g;
    var goog_string_quotRe_ = /\"/g;
    var goog_string_allRe_ = /[&<>\"]/;
   
    function goog_string_htmlEscape(str) {
        // quick test helps in the case when there are no chars to replace, in
        // worst case this makes barely a difference to the time taken
        if (!goog_string_allRe_.test(str)) return str;
   
        // str.indexOf is faster than regex.test in this case
        if (str.indexOf('&') != -1) {
                str = str.replace(goog_string_amperRe_, '&amp;');
        }
        if (str.indexOf('<') != -1) {
                str = str.replace(goog_string_ltRe_, '&lt;');
        }
        if (str.indexOf('>') != -1) {
                str = str.replace(goog_string_gtRe_, '&gt;');
        }
        if (str.indexOf('"') != -1) {
                str = str.replace(goog_string_quotRe_, '&quot;');
        }
        return str;
    }
    ;
   
   
    function goog_string_htmlEscape_typeOf(str) {
        // quick test helps in the case when there are no chars to replace, in
        // worst case this makes barely a difference to the time taken
        if (typeof str !== 'string' || !goog_string_allRe_.test(str)) return str;
   
        // str.indexOf is faster than regex.test in this case
        if (str.indexOf('&') != -1) {
                str = str.replace(goog_string_amperRe_, '&amp;');
        }
        if (str.indexOf('<') != -1) {
                str = str.replace(goog_string_ltRe_, '&lt;');
        }
        if (str.indexOf('>') != -1) {
                str = str.replace(goog_string_gtRe_, ' &gt;');
        }
        if (str.indexOf('"') != -1) {
                str = str.replace(goog_string_quotRe_, '&quot;');
        }
        return str;
    }
   
    var goog_string_htmlEscape_typeOf_cachedString = (function(string_escape_amper, string_escape_quot, string_escape_lt, string_escape_gt
                          , string_unescape_amper, string_unescape_quot, string_unescape_lt, string_unescape_gt
                          , RE_escape_test_all
                          , createGlobalRegExp
        ) {
                var RE_escape_amper = createGlobalRegExp(string_unescape_amper)
                        , RE_escape_quot = createGlobalRegExp(string_unescape_quot)
                        , RE_escape_lt = createGlobalRegExp(string_unescape_lt)
                        , RE_escape_gt = createGlobalRegExp(string_unescape_gt)
                ;
               
                return function(str) {
                       
                        // quick test helps in the case when there are no chars to replace, in
                        // worst case this makes barely a difference to the time taken
                        if( typeof str !== 'string' || !RE_escape_test_all.test(str) ){
                                return str;
                        }
   
                        // str.indexOf is faster than regex.test in this case
                        if ( ~str.indexOf(string_unescape_amper) ) {
                                str = str.replace(RE_escape_amper, string_escape_amper);
                        }
                        if ( ~str.indexOf(string_unescape_quot) ) {
                                str = str.replace(RE_escape_quot, string_escape_quot);
                        }
                        if ( ~str.indexOf(string_unescape_lt) ) {
                                str = str.replace(RE_escape_lt, string_escape_lt);
                        }
                        if ( ~str.indexOf(string_unescape_gt) ) {
                                str = str.replace(RE_escape_gt, string_escape_gt);
                        }
                       
                        return str;
                };
   
        }).call(null, "&amp;", "&quot;", "&lt;", "&gt;", "&", "\"", "<", ">", /[&<>\"]/, function(val){ return new RegExp(val, "g") });
   
   
    var goog_string_htmlEscape_typeOf_cachedString2 =           (function(string_escape_amper, string_escape_quot, string_escape_lt, string_escape_gt
                          , string_unescape_amper, string_unescape_quot, string_unescape_lt, string_unescape_gt
                          , RE_escape_test_all
                          , createGlobalRegExp
                          , RE_escape_amper, RE_escape_quot, RE_escape_quot2, RE_escape_lt
        ) {
                var args = arguments;
               
                for(var i = 4 ; i < 8 ; ++i) {
                        args[i + 6] = createGlobalRegExp(args[i]);
                }
               
                return function(str) {                 
                        // quick test helps in the case when there are no chars to replace, in
                        // worst case this makes barely a difference to the time taken
                        if( typeof str !== 'string' || !RE_escape_test_all.test(str) ){
                                return str;
                        }
                       
                        for(var i = 0 ; i < 4 ; ++i) {
                                // str.indexOf is faster than regex.test in this case
                                if( ~str.indexOf(args[i + 4]) ) {
                                        str = str.replace(args[i + 10], args[i]);
                                }      
                        }
                       
                        return str;
                };
        }).call(null, "&amp;", "&quot;", "&lt;", "&gt;", "&", "\"", "<", ">", /[&<>\"]/, function(val){ return new RegExp(val, "g") });
   
   
   
   
   
    var createGlobalRegExp = function(val){ return new RegExp(val, "g") };
    var RE_escape_test_all = /[&<>\"]/;
    var array_for_escape_and_unescape = [
                  "&amp;", "&quot;", "&lt;", "&gt;"
                , "&",     "\"",     "<",    ">"
        ];
   
    for(var i = 4 ; i < 8 ; ++i) {
        array_for_escape_and_unescape[i + 4] = createGlobalRegExp(array_for_escape_and_unescape[i]);
    }
   
    function  goog_string_htmlEscape_typeOf_cachedString3(str) {
       
        // quick test helps in the case when there are no chars to replace, in
        // worst case this makes barely a difference to the time taken
        if( typeof str !== 'string' || !RE_escape_test_all.test(str) ){
                return str;
        }
       
        for(var i = 0 ; i < 4 ; ++i) {
                // str.indexOf is faster than regex.test in this case
                if( ~str.indexOf(array_for_escape_and_unescape[i + 4]) ) {
                        str = str.replace(array_for_escape_and_unescape[i + 8], array_for_escape_and_unescape[i]);
                }      
        }
       
        return str;
    };
   
   
   
};
</script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
htmlEscape
for (var i = 0, n = strings.length; i < n; i += 1) {
  htmlEscape(strings[i]);
}
pending…
goog.string.htmlEscape
for (var i = 0, n = strings.length; i < n; i += 1) {
  goog_string_htmlEscape(strings[i]);
}
pending…
htmlEscape + typeOf
for (var i = 0, n = strings.length; i < n; i += 1) {
  htmlEscape_typeOf(strings[i]);
}
pending…
goog.string.htmlEscape + typeOf
for (var i = 0, n = strings.length; i < n; i += 1) {
  goog_string_htmlEscape_typeOf(strings[i]);
}
pending…
goog.string.htmlEscape + typeOf + cheched strings
for (var i = 0, n = strings.length; i < n; i += 1) {
  goog_string_htmlEscape_typeOf_cachedString(strings[i]);
}
pending…
goog.string.htmlEscape + typeOf + cheched strings #2
for (var i = 0, n = strings.length; i < n; i += 1) {
  goog_string_htmlEscape_typeOf_cachedString2(strings[i]);
}
pending…
goog.string.htmlEscape + typeOf + cheched strings #3
for (var i = 0, n = strings.length; i < n; i += 1) {
  goog_string_htmlEscape_typeOf_cachedString3(strings[i]);
}
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment