Template Compile Performance Poor on iOS 5 #134

Closed
tmquinn opened this Issue Nov 1, 2011 · 12 comments

Projects

None yet

4 participants

@tmquinn
tmquinn commented Nov 1, 2011

I'm developing a project for iOS using Phonegap & Handlebars. The average time to run Handlebars.compile(foo) in iOS 4.2 is ~140ms to compile the same template in iOS 5 is ~1230ms

@wagenet
Collaborator
wagenet commented Nov 1, 2011

@tmquinn: What's your template look like?

@wagenet
Collaborator
wagenet commented Nov 1, 2011

Also are you on master? or the last official release?

@tmquinn
tmquinn commented Nov 1, 2011

Some more numbers: (times are absolute)

iOS5 & Handlebars.1.0.0.beta.3.js

2011-11-01 15:55:22.018 GWMobile[2208:707] [INFO] Pre compile: 176
2011-11-01 15:55:22.026 GWMobile[2208:707] [INFO] Post compile: 1404
2011-11-01 15:55:22.038 GWMobile[2208:707] [INFO] Pre handlebar template: 1405
2011-11-01 15:55:22.047 GWMobile[2208:707] [INFO] Post handlebar template: 1417

iOS5 & Handlebars [master]

2011-11-01 15:58:41.761 GWMobile[2226:707] [INFO] Pre compile: 173
2011-11-01 15:58:41.772 GWMobile[2226:707] [INFO] Post compile: 173
2011-11-01 15:58:41.782 GWMobile[2226:707] [INFO] Pre handlebar template: 173
2011-11-01 15:58:41.795 GWMobile[2226:707] [INFO] Post handlebar template: 1411

Looks like the bulk of the performance issue moved to the rendering component.

The template from the previous example is:

<div class="vbox modalBodyContent" data-role="content">
    <div class="window9_trans"><div class="window_bracket_scan"><div class="window_scan">
        <div class="window9">
    <div class="hbox modalDescription">
                <div class="buildMenuImageWindow">
                    <div class="modalDescriptionGraphic buildMenuImg building building_{{buildingTypeId}}">
                            <div style="width:55px;height:55px;display:inline-block;"></div><!-- Yea, this is really needed -->
                    </div>
                </div>
        <div class="flexBox">{{description}}</div>
        </div>
        </div><!-- end inner window -->

    <div class="hbox modalNextLevel">
        <span class="flexBox modalNextLevelTitle">{{nextLevelTitle}}</span>
        <span class="flexBox modalNextLevelContent">{{nextLevelContent}}</span>
    </div>
    </div></div></div><!-- end window -->



    {{#unless maxedLevel}}
    <div class="vbox modalRequirements">
        <div class="hbox {{#if isBuildingInSlot}}packJustify{{else}}packEnd{{/if}} modalUpgradeButtons">
            {{#if isBuildingInSlot}}
            <div class="modalUpgradingLevelTitle">{{{upgradingLevelTitle}}}</div>
            <div class="clockIcon"></div>
            {{/if}}

            {{#if canBuild}}
            {{#unless isBuildingInSlot}}
            <div class="clockIcon"></div>
            <div class="modalTimeDisplay">{{time}}</div>
            {{/unless}}
            {{/if}}

            {{#unless isBuildingInSlot}}
            {{#unless canBuild}}
            <!--
            <div>
                            <a class="button buttonGemGreen"><div class="buttonText">{{shopTxt}}</div></a>
            </div>
            -->
            {{/unless}}
            {{/unless}}

            <div>
                {{#unless isBuildingInSlot}}
                <a {{#if canBuild}}onclick="{{upgradeInstantlyFn}}"{{/if}} class="button buttonGemGreen {{#unless canBuild}} buttonDisabled{{/unless}}"><div class="buttonText">{{{upgradeInstantlyTxt}}}</div></a>
                <a {{#if canBuild}}onclick="{{upgradeFn}}"{{/if}} class="button buttonGemOrange {{#unless canBuild}} buttonDisabled{{/unless}}"><div class="buttonText">{{upgradeTxt}}</div></a>
                {{else}}

                <div class="modalProgressBar modalConstructProgressBar">
                    <div id="construct{{id}}" class="modalProgressBarIndicator" style="width:{{width}}%">{{timeStr}}</div>
                </div>
                {{/unless}}
            </div>
        </div>

        {{#if isBuildingInSlot}}
        <div class="packEnd modalSpeedUpButtons">
                    <a class="button buttonGemGreen" onclick="{{{fn1Fn}}}"><div class="buttonText">{{fn1Text}}</div></a>
                    <a class="button buttonGemGreen" onclick="{{{fn2Fn}}}"><div class="buttonText">{{fn2Text}}</div></a>
        </div>
        {{/if}}
                <div class="window9_trans"><div class="window_bracket_scan"><div class="window_scan">
        <div class="window9">
        <div id="modalRequirements">
            <table class="modalRequirementsTable">
                <tr>
                    <th>Resource</th>
                    <th>Required</th>
                    <th>You Own</th>
                </tr>
                {{#each requirements}}
                <tr class="{{#if reqMet}}reqMet{{else}}reqNotMet{{/if}} requirementType_{{id}}">
                    <td class="modalRequirementsLabel"><div class="requirementIcon"></div>{{title}}</td>
                    <td class="modalRequirementsValue">{{required}}</td>
                    <td class="modalRequirementsOwn">{{owned}}</td>
                </tr>
                {{/each}}
            </table>
        </div>
                </div><!--end inner window-->
                </div></div></div><!-- end window -->
    </div>
    {{/unless}}


        {{#unless newBuild}}
    <div class="hbox demolishButtons">
            {{#if canDeconstruct}}<a class="button buttonGemRed" onclick="KB.Building.deconstructBuilding('{{slotNo}}')"><div class="buttonText">{{deconstructStr}}</div></a>{{/if}}
            {{#if canDestroy}}<a class="button buttonGemRed" onclick="KB.Building.destructBuilding('{{slotNo}}')"><div class="buttonText">{{destroyStr}}</div></a>{{/if}}
    </div>
    {{/unless}}
</div>
@wycats
Owner
wycats commented Nov 1, 2011

In general, you should use the pre-compiler for mobile apps. It is available as an npm package at http://search.npmjs.org/#/handlebars and will completely eliminate the runtime need to compile as well as significantly shrink the required JS to ship with your app.

@tmquinn
tmquinn commented Nov 1, 2011

Ya.. I was just noticing that was finally released. Will most likely take that route...

@tmquinn
tmquinn commented Nov 10, 2011

So it does not seem to be a compile issue but a render issue. There is a huge spike in JS activity on iOS5 when templates are rendering, as compared to pre iOS5. I'm profiling it now, but I'm curious if anyone else is encountering this issue...

@tmquinn
tmquinn commented Nov 10, 2011

After some prelimary testing, there's a great deal of activity associated running on iOS5 with JSC::Yarr:Interpreter:matchDisjunction that does not show any activity at all on early versions of iOS

@wagenet
Collaborator
wagenet commented Nov 23, 2011

@tmquinn, just to clarify, the slowness still occurs with pre-compiled templates?

@tmquinn
tmquinn commented Nov 28, 2011

Sorry, no... just compiling

@wycats
Owner
wycats commented Dec 28, 2011

@tmquinn this seems likely to be a regression in Mobile Safari. In any event, you should definitely be using precompiled templates in resource constrained environments like mobile devices.

Please reopen this ticket if you see the same issue with desktop Safari, and thanks for your patience with this ticket.

@wycats wycats closed this Dec 28, 2011
@tmquinn
tmquinn commented Jan 3, 2012

Alls good. Am using all pre-compiled templates now. The other hitch I saw was stupid mobSafari DOM swampyness

@cherouvim

I confirm this. Phonegap uses UIWebView and this doesn't use the nitro js engine. This makes even small templates rendering very slow. Compilation time is insignificant. Executing the function that comes out of .compile() is very very slow in the UIWebView.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment