DataTemplate: solution to performance problems with WinJS Templates and binding

Problem: peformance issues with WinJS Templates and binding

WinJS Templates and Binding belongs to core parts of WinJS. Especially they fit very well into MVVM model, declarative binding, separation of concerns (UI logic contains really only UI logic)

Template rendering has the following high-level steps:

  1. optionaly create new container element which will contain a final rendered HTML – this step is optional because a result container can be passed as argument to the method)
  2. clone the template and append it into the container
  3. call WinJS.UI.processAll function on the root
  4. call WinJS.Binding.processAll function on the root and passed binding context objects (aka datacontext object)
  5. return the result

In addition, the whole process is wrapped into promises.

This process works quite well and you can achieve nice results with it. The problem starts when you try to finetune the performance. This is the slowest way of rendering item. There are several other ways which you can find in any WinJS docs/books.

WinJS Template and declarative binding is the slowest approach but the most flexible and I’d like to use it as often as possible but the performance has to be improved.

Let’s measure it!

Download MeasuringTemplatePerformance.zip and run the sample! (after downloading the file, remove extension docx, then unzip it) The sample I attached to this blog post is used to generate the color palette with the divs, using CSS3 grid layout. It does it in different ways and it measure the time spent.

Let’s review each solution.

Manual render

This is the fastest way and we will use it as our unit of measure. It’s the quickest way (at least for me) how to solve our problem. The only issue is that all UI logic (creating DOM elements, setting properties, etc) are done in codebehind, so there is NO separation of concerns.

Cloning render

It differs from manual process in the way how DOM elements are created – they are cloned form a template (do not mix it with WinJS template). In this case, the template is DOM element (acts as prototype) and we create cloned DOM element from the prototype and again, manualy set properties.
This is cca 3x slower than manual and still we violate separation of concerns.

Template, manual binding, manual placing in DOM

This approach uses WinJS template and its render method but it manually sets the properties (it doesnt use binding mechanism at all).
This is cca 7x slower than manual approach and again we violate separation of concerns.

Template, manual binding, auto placing in DOM

Similar approach as the previous case with just one difference: the result is directly added into DOM.
This is cca 11x slower then manual approach and again we violate separation of concerns.

Template, declarative binding, auto placing in DOM

This approach uses fully standard WinJS way of rendering, binding and adding the result to the DOM.
This is cca 30x slower than manual rendering but with full separation of concerns.

How to make the situation better?

The only solution is to reduce JS code to be executed. The source of the issue are two:

  1. calling WinJS.UI.processAll inside WinJS.Binding.Template.render – it could be totaly skipped as we don’t need to process any inner win controls.
  2. calling WinJS.Binding.processAll inside WinJS.Binding.Template.render – It could be rapidly enhanced. It’s overlook very often that WinJS.Binding.processAll has an optional argument called “bindingCache”. It is an object with specific interface and several usages:
    1. store all binding created during the binding process,
    2. cache parse all bindings found in the template
    3. stores all elements IDs with the bindings

Passing “bindingCache” can be reused for future binding process and it will speed up the binding process very much. Let’s see it in the action.

Template, cloning, declarative binding with binding cache, manual placing in DOM

This approach runs the binding process over the template element just to build the binding cache. Then for each data the template element is cloned and bound with support of binding cache. The difference is huge, IMHO.
This approach is slower only cca 4x than manual approach but follows separation of UI logic.

MvvmJS.UI.DataTemplate, declarative binding, auto placing in DOM

It is possible to go further and speed-up binding process with binding cache – binding process uses query selector to find all elements with data-win-bind attribute. I created a control, called MvvmJS.UI.DataTemplate which implements this logic and uses binding cache.

This approach is very simple and it’s slower only 3x than the manual approach but with full declarative binding and it wins for me. Especialy when the templates will be more complicated and it will be necessary to react on any data change.

Solution – MvvmJS.UI.DataTemplate

Usage of MvvmJS.UI.DataTemplate (UI/HTML part)

    <div id="dataTemplate">
        <div></div>
    </div>

Usage of MvvmJS.UI.DataTemplate (UI/code behind part)

                var cellTemplate = document.getElementById("dataTemplate");
                cellTemplate.winControl || WinJS.UI.processAll(cellTemplate);
                cells.forEach(function (cell) {
                    cellTemplate.winControl.render(cell, grid);
                });

DataTemplate class can be found in this project. MvvmJS project will be upgraded later (this month) with all new controls and logic.

2 thoughts on “DataTemplate: solution to performance problems with WinJS Templates and binding

  1. The solution that uses MvvmJS.UI.DataTemplate is great. I like this solution. I hope the problem will be solved in the near future for the default mechanism also.
    On the other hand, a Metro application should be clean and simple. It should do only one thing. Because of this, scenarios where we need a lot of binding should be double check. Maybe we don’t a screen with this level of complexity.

Leave a comment