Question

I'm trying to figure out why in my jsperf below, the javascript string templates are so much slower than the equivalent knockout.js templates. The goal of the test is to measure full page, and partial page changes, link in a Single Page Application.

http://jsperf.com/knockoutvjquery/6

Originally I was going to test just the speed of underscore.js templates, but now I'm just writing raw hard coded strings to the dom. It seems that when the speed tests are simple dom elements they are fast, but once I get into "real world" situations, the knockout tests are faster. What gives?

Preparation code HTML

<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="//cloud.github.com/downloads/SteveSanderson/knockout/knockout-2.1.0.js"></script>


<div id="jquery"></div>

<div id="knockout">
<div data-bind="foreach:Zones">
        <div data-bind="
            style:{ position: 'absolute', top: ZoneY, left: ZoneX, width: Width, height: Height },
            foreach:Layouts
            ">
            <!-- ko if: ShowText -->
                <div style="position: absolute;" data-bind="
                    text:Value, 
                    style:{  
                        top: YPosition, 
                        left: XPosition,
                        color: FontColor,
                        'font-family': FontFamilyName,
                        'font-size': FontSize,
                        'font-weight': FontWeight
                    }
                "></div>
            <!-- /ko -->

            <!-- ko if: ShowHtml -->
                <div style="position: absolute;" data-bind="
                    html:Value, 
                    style:{  
                        top: YPosition, 
                        left: XPosition,
                        color: FontColor,
                        'font-family': FontFamilyName,
                        'font-size': FontSize,
                        'font-weight': FontWeight
                    }
                    "></div>
            <!-- /ko -->

            <!-- ko if: ShowImage -->

                <!-- ko if: IsSWF -->
                    <embed data-bind="attr:{src:ImageURL}, style:{ width: Width, height : Height }">
                <!-- /ko -->

                <!-- ko ifnot: IsSWF -->
                    <img data-bind="attr:{src:ImageURL}, style:{ width: Width, height : Height }" />
                <!-- /ko -->

            <!-- /ko -->
        </div>
    </div>
</div>

Define Setup for all tests

var d1 = '<div style="position: absolute; top: 0px; left: 0px; width: 1360px; height: 768px; "></div>'

var d2 = '<div style="position: absolute; top: 0px; left: 0px; width: 1360px; height: 280px; "><embed  src="http://ronincastx.ronincast.com/CMS/Media/54638DC3-DC3C-4EAC-8698-334EB681B6B8_Widener-Expo-1.2-1360x280.swf" style="width: 1360px; height: 275px; "></div>'

var d3 = '<div  style="position: absolute; top: 275px; left: 0px; width: 1360px; height: 493px; "><img  src="http://ronincastx.ronincast.com/CMS/Media/94A94FC5-AB43-4218-B5CA-15C6F37D3152_WidenerU-Expo-1.2-BKGD.png" style="width: 1360px; height: 493px; "></div>'

var d4 = '<div  style="position: absolute; top: 650px; left: 0px; width: 118px; height: 118px; "><embed  src="http://ronincastx.ronincast.com/CMS/Media/0C484985-6038-47B8-8A1D-BF7FB33B6B56_Be Well-Footer-140x140.swf" style="width: 140px; height: 140px; "></div>'

var d5 = '<div style="position: absolute; top: 650px; left: 160px; width: 130px; height: 118px; "><img  src="http://ronincastx.ronincast.com/CMS/Media/a91e8733-d27f-4f86-81e3-df4f93efad67_01Just4U-Icons-LowerFat.png" style="width: 130px; height: 118px; "> </div>'

var d6 = '<div  style="position: absolute; top: 650px; left: 310px; width: 130px; height: 118px; "></div>'

var d7 = '<div  style="position: absolute; top: 650px; left: 460px; width: 130px; height: 118px; "></div>'

var d8 = '<div  style="position: absolute; top: 650px; left: 610px; width: 130px; height: 118px; "></div>'

var d9 = '<div style="position: absolute; top: 650px; left: 760px; width: 130px; height: 118px; "></div>'

var d10 = '<div style="position: absolute; top: 370px; left: 0px; width: 680px; height: 126px; "> <div style="position: absolute; top: 79px; left: 84px; color: rgb(0, 0, 0); font-size: 24px; font-weight: bold; " > Create your customized omelet with your choice of: ham, turkey, spinach, green peppers, onions, and mushrooms</div><div style="position: absolute; top: 0px; left: 84px; color: rgb(0, 0, 0); font-size: 50px; font-weight: bold; " >Customized Omelet</div></div>'

var d11 = '<div  style="position: absolute; top: 501px; left: 0px; width: 680px; height: 126px; "> <img  src="http://ronincastx.ronincast.com/CMS/Media/2509594F-404F-4818-BB26-30C91ADB57B9_transparent-image.png" style="width: 25px; height: 25px; "></div>'

var d12 = '<div style="position: absolute; top: 370px; left: 680px; width: 680px; height: 126px; "><img  src="http://ronincastx.ronincast.com/CMS/Media/2509594F-404F-4818-BB26-30C91ADB57B9_transparent-image.png" style="width: 25px; height: 25px; "> </div>'

var d13 = '<div  style="position: absolute; top: 501px; left: 680px; width: 680px; height: 126px; "><img  src="http://ronincastx.ronincast.com/CMS/Media/2509594F-404F-4818-BB26-30C91ADB57B9_transparent-image.png" style="width: 25px; height: 25px; "></div>'

var d14 = '<div  style="position: absolute; top: 290px; left: 0px; width: 680px; height: 77px; "><div style="position: absolute; top: 0px; left: 84px; color: rgb(0, 0, 0); font-size: 72px; font-weight: bold; "></div></div>'

var d15 = '<div  style="position: absolute; top: 290px; left: 680px; width: 680px; height: 77px; "><div style="position: absolute; top: 0px; left: 84px; color: rgb(0, 0, 0); font-size: 72px; font-weight: bold; "></div></div>'

var displayViewModel = function () {
    var self = this;

    this.init = function () {

    };

    this.Events = ko.observableArray();

    this.Zones = ko.computed({
        read: function () {
            if(self.Events().length == 0) {
                return [];
            }

            return self.Events()[0].Presentations[0].Zones;
        },
        deferEvaluation: true
    });
};
var events = [
        {
            "Id": 38312,
            "Presentations": [
                {
                    "Zones": [
                        {
                            "ZoneX": "0px",
                            "ZoneY": "0px",
                            "Layouts": [],
                            "Height": "768px",
                            "Width": "1360px"
                        },
                        {
                            "ZoneX": "0px",
                            "ZoneY": "0px",
                            "Layouts": [
                                {
                                    "XPosition": "0px",
                                    "YPosition": "0px",
                                    "Width": "1360px",
                                    "Height": "275px",
                                    "Value": "54638dc3-dc3c-4eac-8698-334eb681b6b8",
                                    "ValueType": 12,
                                    "FontSize": "20px",
                                    "FontFamilyName": "Verlag Black",
                                    "FontWeight": "Normal",
                                    "FontColor": "#000000",
                                    "FileName": "54638DC3-DC3C-4EAC-8698-334EB681B6B8_Widener-Expo-1.2-1360x280.swf",
                                    "ShowText": false,
                                    "ShowImage": true,
                                    "ShowHtml": false,
                                    "IsSWF": true,
                                    "ImageURL": "http://ronincastx.ronincast.com/CMS/Media/54638DC3-DC3C-4EAC-8698-334EB681B6B8_Widener-Expo-1.2-1360x280.swf"
                                }
                            ],
                            "Height": "280px",
                            "Width": "1360px"
                        },
                        {
                            "ZoneX": "0px",
                            "ZoneY": "275px",
                            "Layouts": [
                                {
                                    "XPosition": "0px",
                                    "YPosition": "0px",
                                    "Width": "1360px",
                                    "Height": "493px",
                                    "Value": "94a94fc5-ab43-4218-b5ca-15c6f37d3152",
                                    "ValueType": 12,
                                    "FontSize": "20px",
                                    "FontFamilyName": "Verlag Black",
                                    "FontWeight": "Normal",
                                    "FontColor": "#000000",
                                    "FileName": "94A94FC5-AB43-4218-B5CA-15C6F37D3152_WidenerU-Expo-1.2-BKGD.png",
                                    "ShowText": false,
                                    "ShowImage": true,
                                    "ShowHtml": false,
                                    "IsSWF": false,
                                    "ImageURL": "http://ronincastx.ronincast.com/CMS/Media/94A94FC5-AB43-4218-B5CA-15C6F37D3152_WidenerU-Expo-1.2-BKGD.png"
                                }
                            ],
                            "Height": "493px",
                            "Width": "1360px"
                        },
                        {
                            "ZoneX": "0px",
                            "ZoneY": "650px",
                            "Layouts": [
                                {
                                    "XPosition": "0px",
                                    "YPosition": "0px",
                                    "Width": "140px",
                                    "Height": "140px",
                                    "Value": "0c484985-6038-47b8-8a1d-bf7fb33b6b56",
                                    "ValueType": 12,
                                    "FontSize": "20px",
                                    "FontFamilyName": "Verlag Black",
                                    "FontWeight": "Normal",
                                    "FontColor": "#000000",
                                    "FileName": "0C484985-6038-47B8-8A1D-BF7FB33B6B56_Be Well-Footer-140x140.swf",
                                    "ShowText": false,
                                    "ShowImage": true,
                                    "ShowHtml": false,
                                    "IsSWF": true,
                                    "ImageURL": "http://ronincastx.ronincast.com/CMS/Media/0C484985-6038-47B8-8A1D-BF7FB33B6B56_Be Well-Footer-140x140.swf"
                                }
                            ],
                            "Height": "118px",
                            "Width": "118px"
                        },
                        {
                            "ZoneX": "160px",
                            "ZoneY": "650px",
                            "Layouts": [
                                {
                                    "XPosition": "0px",
                                    "YPosition": "0px",
                                    "Width": "130px",
                                    "Height": "118px",
                                    "Value": "a91e8733-d27f-4f86-81e3-df4f93efad67",
                                    "ValueType": 12,
                                    "FontSize": "20px",
                                    "FontFamilyName": "Verlag Black",
                                    "FontWeight": "Normal",
                                    "FontColor": "#000000",
                                    "FileName": "a91e8733-d27f-4f86-81e3-df4f93efad67_01Just4U-Icons-LowerFat.png",
                                    "ShowText": false,
                                    "ShowImage": true,
                                    "ShowHtml": false,
                                    "IsSWF": false,
                                    "ImageURL": "http://ronincastx.ronincast.com/CMS/Media/a91e8733-d27f-4f86-81e3-df4f93efad67_01Just4U-Icons-LowerFat.png"
                                }
                            ],
                            "Height": "118px",
                            "Width": "130px",
                        },
                        {
                            "ZoneX": "310px",
                            "ZoneY": "650px",
                            "Layouts": [],
                            "Height": "118px",
                            "Width": "130px",

                        },
                        {
                            "ZoneX": "460px",
                            "ZoneY": "650px",
                            "Layouts": [],
                            "Height": "118px",
                            "Width": "130px"
                        },
                        {
                            "ZoneX": "610px",
                            "ZoneY": "650px",
                            "Layouts": [],
                            "Height": "118px",
                            "Width": "130px"
                        },
                        {
                            "ZoneX": "760px",
                            "ZoneY": "650px",
                            "Layouts": [],
                            "Height": "118px",
                            "Width": "130px"
                        },
                        {
                            "ZoneX": "0px",
                            "ZoneY": "370px",
                            "Layouts": [
                                {
                                    "XPosition": "84px",
                                    "YPosition": "79px",
                                    "Width": "595px",
                                    "Height": "40px",
                                    "Value": "Create your customized omelet with your choice of: ham, turkey, spinach, green peppers, onions, and mushrooms",
                                    "ValueType": 3,
                                    "FontSize": "24px",
                                    "FontFamilyName": "",
                                    "FontWeight": "bold",
                                    "FontColor": "#000000",
                                    "ShowText": true,
                                    "ShowImage": false,
                                    "ShowHtml": false,
                                    "IsSWF": false,
                                    "ImageURL": ""
                                },
                                {
                                    "XPosition": "84px",
                                    "YPosition": "0px",
                                    "Width": "595px",
                                    "Height": "52px",
                                    "Value": "Customized Omelet",
                                    "ValueType": 1,
                                    "FontSize": "50px",
                                    "FontFamilyName": "",
                                    "FontWeight": "bold",
                                    "FontColor": "#000000",
                                    "ShowText": true,
                                    "ShowImage": false,
                                    "ShowHtml": false,
                                    "IsSWF": false,
                                    "ImageURL": ""
                                }
                            ],
                            "Height": "126px",
                            "Width": "680px",
                        },
                        {
                            "ZoneX": "0px",
                            "ZoneY": "501px",
                            "Layouts": [
                                {
                                    "XPosition": "53px",
                                    "YPosition": "11px",
                                    "Width": "25px",
                                    "Height": "25px",
                                    "Value": "2509594f-404f-4818-bb26-30c91adb57b9",
                                    "ValueType": 12,
                                    "FontSize": "20px",
                                    "FontFamilyName": "Verlag Black",
                                    "FontWeight": "Normal",
                                    "FontColor": "#000000",
                                    "FileName": "2509594F-404F-4818-BB26-30C91ADB57B9_transparent-image.png",
                                    "ShowText": false,
                                    "ShowImage": true,
                                    "ShowHtml": false,
                                    "IsSWF": false,
                                    "ImageURL": "http://ronincastx.ronincast.com/CMS/Media/2509594F-404F-4818-BB26-30C91ADB57B9_transparent-image.png"
                                }
                            ],
                            "Height": "126px",
                            "Width": "680px",
                        },
                        {
                            "ZoneX": "680px",
                            "ZoneY": "370px",
                            "Layouts": [
                                {
                                    "XPosition": "53px",
                                    "YPosition": "11px",
                                    "Width": "25px",
                                    "Height": "25px",
                                    "Value": "2509594f-404f-4818-bb26-30c91adb57b9",
                                    "ValueType": 12,
                                    "FontSize": "20px",
                                    "FontFamilyName": "Verlag Black",
                                    "FontWeight": "Normal",
                                    "FontColor": "#000000",
                                    "FileName": "2509594F-404F-4818-BB26-30C91ADB57B9_transparent-image.png",
                                    "ShowText": false,
                                    "ShowImage": true,
                                    "ShowHtml": false,
                                    "IsSWF": false,
                                    "ImageURL": "http://ronincastx.ronincast.com/CMS/Media/2509594F-404F-4818-BB26-30C91ADB57B9_transparent-image.png"
                                }
                            ],
                            "Height": "126px",
                            "Width": "680px",
                        },
                        {
                            "ZoneX": "680px",
                            "ZoneY": "501px",
                            "Layouts": [
                                {
                                    "XPosition": "53px",
                                    "YPosition": "11px",
                                    "Width": "25px",
                                    "Height": "25px",
                                    "Value": "2509594f-404f-4818-bb26-30c91adb57b9",
                                    "ValueType": 12,
                                    "FontSize": "20px",
                                    "FontFamilyName": "Verlag Black",
                                    "FontWeight": "Normal",
                                    "FontColor": "#000000",
                                    "FileName": "2509594F-404F-4818-BB26-30C91ADB57B9_transparent-image.png",
                                    "ShowText": false,
                                    "ShowImage": true,
                                    "ShowHtml": false,
                                    "IsSWF": false,
                                    "ImageURL": "http://ronincastx.ronincast.com/CMS/Media/2509594F-404F-4818-BB26-30C91ADB57B9_transparent-image.png"
                                }
                            ],
                            "Height": "126px",
                            "Width": "680px"
                        },
                        {
                            "ZoneX": "0px",
                            "ZoneY": "290px",
                            "Layouts": [
                                {
                                    "XPosition": "84px",
                                    "YPosition": "0px",
                                    "Width": "596px",
                                    "Height": "77px",
                                    "Value": "",
                                    "ValueType": 1,
                                    "FontSize": "72px",
                                    "FontFamilyName": "",
                                    "FontWeight": "bold",
                                    "FontColor": "#000000",
                                    "ShowText": true,
                                    "ShowImage": false,
                                    "ShowHtml": false,
                                    "IsSWF": false,
                                    "ImageURL": ""
                                }
                            ],
                            "Height": "77px",
                            "Width": "680px"
                        },
                        {
                            "ZoneX": "680px",
                            "ZoneY": "290px",
                            "Layouts": [
                                {
                                    "XPosition": "84px",
                                    "YPosition": "0px",
                                    "Width": "596px",
                                    "Height": "77px",
                                    "Value": "",
                                    "ValueType": 1,
                                    "FontSize": "72px",
                                    "FontFamilyName": "",
                                    "FontWeight": "bold",
                                    "FontColor": "#000000",
                                    "ShowText": true,
                                    "ShowImage": false,
                                    "ShowHtml": false,
                                    "IsSWF": false,
                                    "ImageURL": ""
                                }
                            ],
                            "Height": "77px",
                            "Width": "680px"
                        }
                    ]
                }
            ]
        }
    ];

var masterViewModel = new displayViewModel();

var knockoutElement = $('#knockout')[0];

ko.applyBindings(masterViewModel, $('#knockout')[0]);

Define teardown for all tests

$('#jquery').empty()

masterViewModel.Events([]);
ko.cleanNode(knockoutElement);

Test 1 - jquery

var tmp = [d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15];
$('#jquery')[0].innerHTML = tmp.join();

Test 2 - knockout

masterViewModel.Events.push.apply(masterViewModel.Events, events);
Was it helpful?

Solution

For anonymous templates (what is used for if, ifnot, with, and foreach), the elements are stored and cloned when the actual rendering happens. This is true for all browsers except IE < 9.

So, the Knockout test is able to do cloneNode on existing nodes rather than parsing them from strings like the jQuery test is doing.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top