jQuery fragment cache

Benchmark created on


Description

Compare the effect of a buildFragment cache on the speed of jQuery DOM manipulations, hopefully analogous to real-world use (pulled from https://github.com/jquery/jquery/blob/9ae6b1a019553e95a6205d5c42ff7fa25e7a482e/test/unit/manipulation.js).

Preparation HTML

<script src="http://code.jquery.com/jquery-git.js"></script>
<script>var withCache = jQuery.noConflict();</script>

<script src="http://code.jquery.com/jquery-git.js"></script>
<script>
    var withoutCache = jQuery.noConflict();
    withoutCache.buildFragment = function( args, context, scripts ) {
        var fragment;

        context = context || document;
        context = !context.nodeType && context[0] || context;
        context = context.ownerDocument || context;

        fragment = context.createDocumentFragment();
        withoutCache.clean( args, context, fragment, scripts );

        return { fragment: fragment, cacheable: false };
};
</script>


<script>
    function identity ( value ) {
        return value;
    }

    function lambda ( value ) {
        return function() { return value; };
    }

    function test( jQuery, container, inner ) {
        var fn,
            fns = [ identity, lambda ],
            $container = jQuery( container ),
            $inner = $container.find( inner ),
            html = $container.html();

        while ( (fn = fns.shift()) ) {
            // .append
            $container.clone().append( "<span></span>", "<span></span>", "<span></span>");
            jQuery( "<div>inputs<br/><select id='select'><option>default</option></select><input type='checkbox'/><input type='text'/></div>" ).appendTo( $container );
            $container.append( fn("<input name='radiotest' type='radio' checked='checked' />") );
            $container.append( fn("<input name='radiotest2' type='radio' checked    =   'checked' />") );
            $container.append( fn("<input name='radiotest3' type='radio' checked />") );
            $container.append( fn("<input type='radio' checked='checked' name='radiotest4' />") );
            jQuery("<fieldset/>").appendTo( $container ).append( fn("<legend id='legend'>test</legend>") );
            jQuery("#select")
                .append( fn("<option value='appendTest'>Append Test</option>") )
                .append( fn("<OPTION>Test</OPTION>") );
            jQuery("#table").append( fn("<colgroup></colgroup>") );
            jQuery("#table colgroup").append( fn("<col/>") );
            jQuery("#table").append( fn("<caption></caption>") );
            $container
                .append( fn("<select id='appendSelect1'></select>") )
                .append( fn("<select id='appendSelect2'><option>Test</option></select>") );
            jQuery("<input />").attr({ "type": "checkbox", "checked": true }).appendTo( $container );
            jQuery("<input type='radio' name='R1' checked='checked'/>").appendTo( $container );
            jQuery("<div/>").append( fn("option<area/>") );
            jQuery( document.createElement("object") ).appendTo( $container ).append( jQuery("<param type='wmode' name='foo'>") );
            jQuery("<object><param type='baz' name='bar'></object>");
            $container.find("select").append(function( i, val ) {
                return "<option value='appendTest'>Append Test</option>";
            });
            $container.append( fn("<article style='font-size:10px'><section><aside>HTML5 elements</aside></section></article>") );
            $container.append( fn("<article id='article'></article>") );
            jQuery("#article").append( fn("<section>This section should have a pink background.</section>") );
            jQuery("<article><section><aside>HTML5 elements</aside></section></article>").appendTo( $container );
            jQuery.each( [ "start-", "toString", "hasOwnProperty", "append", "here&there!", "-end" ], function( text ) {
                $inner.append( fn(text) );
            });
            $inner.append( fn(42) );

            // .before; .after
            jQuery().before( fn("(") ).after( fn(")") );
            jQuery("<input type='checkbox'/>").before( fn("<div/>") ).after( fn("<div/>") );
            $inner.add( fn("<span/>") ).before( fn("<b>buga</b>") ).after( fn("<b>buga</b>") );
            jQuery("<span/>").add( $inner ).before( fn("<b>buga</b>") ).after( fn("<b>buga</b>") );

            // .wrap
            $inner.contents().wrap( fn("<i></i>") );
            $inner.wrap( fn("<form class='red'><div></div></form>") );
            $inner.wrap( fn("<p></p><div></div>") );
            $inner.wrap( fn("<span></span>") );
            $container.find("input").wrap( fn("<div style='display:none;'></div>") );
            $container.text( fn("<div><b>Hello</b> cruel world!</div>") );
            jQuery("<label/>").wrap( fn("<ul/>") ).wrap( jQuery("<li/>") );

            // .wrapAll
            $container.find("input").wrapAll( fn("<div class='red'><div class='tmp'></div></div>") );

            // .wrapInner
            $container.find("div").wrapInner( fn("<div class='red'><div class='tmp'></div></div>") );
            jQuery("<div/>").wrapInner( fn("<span></span>") );

            // .replaceWith
            jQuery("<div></div>").appendTo( $container ).replaceWith( fn("text") );
            $container.find("input").replaceWith( fn("<b>buga</b>") );
            $inner.replaceWith( fn("<b>buga</b>") );

            // .html
            jQuery("<div></div>").html( fn("<div></div><link></link>") );
            $container.html( fn("<article><section><aside>HTML5 elements</aside></section></article>") );
            $container.html( fn("<object height='355' width='425' classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'>  <param name='movie' value='http://www.youtube.com/v/3KANI2dpXLw&amp;hl=en'>  <param name='wmode' value='transparent'> </object>") );
            $container.html( fn("<object height='355' width='425' type='application/x-shockwave-flash' data='http://www.youtube.com/v/3KANI2dpXLw&amp;hl=en'>  <param name='movie' value='http://www.youtube.com/v/3KANI2dpXLw&amp;hl=en'>  <param name='wmode' value='transparent'> </object>") );
            $container.html( fn("<style>.foobar{color:green;}</style>") );
            $container.html( fn(html) );

            // miscellaneous
            jQuery("<td>");
            jQuery("<scr" + "ipt type='text/filler'>Lorem ipsum dolor sit amet</scr" + "ipt><q><scr" + "ipt type='text/filler'>consectetur adipiscing elit</scr" + "ipt></q>");
        }
    }
</script>

<form id="form">
    <table id="table"></table>
    <span id="nonnodes"><span>hi</span> there <!-- mon ami --></span>
</form>

Test runner

Ready to run.

Testing in
TestOps/sec
with cache
test( withCache, "#form", "#nonnodes" );
ready
without cache
test( withoutCache, "#form", "#nonnodes" );
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.