Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Lazy implementation of chained methods for automatic loop fusion
JavaScript
Branch: master
Pull request Compare This branch is 19 commits behind johnbender:master.

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
external
test
README.md
lazy.js
warning.js

README.md

A Standard For Speed

For either of the proxy objects to have any value, plug-in authors and ideally the jQuery core team, must provide the HTMLElement altering functions that underlie many of the jQuery core methods in one form or another. That is, while many of them don't actually use jQuery.fn.map or jQuery.fn.each they could be implemented that way or the composable alteration could be provided along side. Without those functions end users cannot compose them to reduce the full set iterations for the proposed performance gain. For more information on those ideas please see the following links:

jQuery.WarningProxy

This is a simplification of the original jQuery.LazyProxy (which is still included in the repository for further work). The idea is that developers should receive warnings when they are chaining one or more $.fn methods that iterate over the full set and have the pure function available for composition/fusing.

Operation

This library is only meant as a development tool as its inclusion does incur a performance penalty. Again, it is only meant to alert the developer to areas for quick performance wins. To begin just include jQuery and the proxies library.

<script type="text/javascript" src="jquery.js"></scrip>
<script type="text/javascript" src="warning.js"></script>

Then before your jQuery chains execute

jQuery.WarningProxy.init();

That will alter the jQuery object initialization to include an instance of the jQuery.WarningProxy in the prototype chain above the jQuery object instance but below jQuery.fn where all the methods we know and love reside. Ultimately the library will log a warning to the console if the console object exists on window with the names of the methods that were chained.

jQuery.LazyProxy

This is a proof of concept for automatic loop fusion over jQuery sets using lazy chaining. The ideas behind library and information about the types of $.fn methods that can be defined for this library can be found here.

Operation

Loop fusion is a fairly common performance optimization and in most cases results in must faster code. By making jquery $.fn methods lazy by placing a proxy in the prototype chain between a new jQuery object and its normal prototype $.fn this library tracks and can, in certain cases, perform automatic loop fusion.

<script type="text/javascript" src="jquery.js"></scrip>
<script type="text/javascript" src="lazy.js"></script>

Then before your jQuery chains execute

jQuery.WarningProxy.init();

An example:

var addClassRaw = function( elem, className ){
  elem.setAttribute( "class", elem.getAttribute( "class" ) + " " + className );
  return elem;
};

var clearClassRaw = function( elem ) {
  elem.setAttribute( "class", "" );
  return elem;
};

$.fn.lazyClearClass = $.functor(clearClassRaw);

$.fn.lazyAddClass = $.functor(addClassRaw);

By using the $.functor method provided by LazyProxy the raw HTMLElement function will be mapped over the jQuery set and tagged with the pure method. When the two newly defined $.fn methods are invoked on a jQuery object set:

var $divs = $( "div" ).lazyClearClass().lazyAddClass( "foo" );

nothing happens! That's because the pure functions have been composed and are waiting to be executed either explicitly or by invoking any non lazy $.fn method.

$divs.force()

//OR

$divs.show() // any $.fn will do

Performance

Obviously it's important to measure the situations in which the lazy proxy plugin and the underlying composition actually provide performance benefits. Existing information and planned performance tests are documented below.

Lazy Fusion Performance

Sadly the performance benefits of of the lazy loop fusion appear to be outweighed by the argument juggling required to support arbitrary arguments, and also possibly by the JIT compilers/similar optimizations in modern browsers. A simple jsperf example shows that the vanilla method chaining (unfused loops) beats the LazyProxy approach (lazily fused loops) but looses out to simple fusion through function composition.

You can view the performance setup for the jsperf sample under test/proxies-perf.js

Manual Loop Fusion Performance

In the interest of solidifying my understanding of when and where composition is a win I've constructed a few additional performance tests. At the time of this writing it appears that small element sets with faster/simpler functions provide speedups under compositions.

Performances tests.

  1. Remove attr and remove data composed vs chained
  2. Remove attr composed vs chained simple methods
  3. Closest attr check and remove attr composed vs chained

Performance tests still left TODO

  1. Chaining more than two methods
  2. Very small sets (< 5)
  3. Very large sets (> 100)
Something went wrong with that request. Please try again.