template engines performance dot mustache nunjucks dust swig (v20)

Revision 20 of this benchmark created on


Description

doT vs nunjucks vs mustache vs dust vs swig vs handlebars

Preparation HTML

<div id="main"></div>
<div id="wrapper"></div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="https://rawgithub.com/janl/mustache.js/master/mustache.js"></script>
<script src="http://rawgithub.com/mozilla/nunjucks/master/browser/nunjucks.min.js"></script>
<script src="http://rawgithub.com/olado/doT/master/doT.js"></script>
<script src="http://rawgithub.com/linkedin/dustjs/master/dist/dust-full.min.js"></script>
<script src="http://paularmstrong.github.io/swig/js/swig.min.js"></script>
<script src="http://rawgit.com/components/handlebars.js/v2.0.0/handlebars.min.js"></script>
<script src="https://cdn.rawgit.com/adammark/Markup.js/master/src/markup.min.js"></script>

<script id="mustache" type="text/x-mustache-template">
    <ul class="tweetSearchResultList">
        {{#results}}
            <li>
                <img src="{{profile_image_url}}" alt="{{from_user_name}}"/>
                <p>{{text}}</p>
                <span>{{id}}</span>
                <span>{{created_at}}</span>
            </li>
        {{/results}}
    </ul>
</script><!-- #mustache -->

<script id="nunjucks" type="text/x-nunjucks-template">
    <ul class="tweetSearchResultList">
        {% for item in results %}
            <li>
                <img src="{{ item.profile_image_url }}" alt="{{ item.from_user_name }}"/>
                <p>{{item.text}}</p>
                <span>{{item.id}}</span>
                <span>{{item.created_at}}</span>
            </li>
        {% endfor %}
    </ul>
</script><!-- #nunjucks -->

<script id="dot" type="text/x-dot-template">
    <ul class="tweetSearchResultList">
        {{~it.results :item:index}}
            <li>
                <img src="{{= item.profile_image_url }}" alt="{{= item.from_user_name }}"/>
                <p>{{=item.text}}</p>
                <span>{{=item.id}}</span>
                <span>{{=item.created_at}}</span>
            </li>
        {{~}}
    </ul>
</script><!-- #dot -->

<script id="dust" type="text/x-dust-template">
    <ul class="tweetSearchResultList">
        {#results}
            <li>
                <img src="{profile_image_url}" alt="{from_user_name}"/>
                <p>{text}</p>
                <span>{id}</span>
                <span>{created_at}</span>
            </li>
        {/results}
    </ul>
</script><!-- #dust -->

<script id="swig" type="text/x-swig-template">
    <ul class="tweetSearchResultList">
        {% for item in results %}
            <li>
                <img src="{{ item.profile_image_url }}" alt="{{ item.from_user_name }}"/>
                <p>{{item.text}}</p>
                <span>{{item.id}}</span>
                <span>{{item.created_at}}</span>
            </li>
        {% endfor %}
    </ul>
</script><!-- #swig -->

<script id="handlebars" type="text/x-handlebars-template">
    <ul class="tweetSearchResultList">
        {{#each results}}
            <li>
                <img src="{{profile_image_url}}" alt="{{from_user_name}}"/>
                <p>{{text}}</p>
                <span>{{id}}</span>
                <span>{{created_at}}</span>
            </li>
        {{/each}}
    </ul>
</script><!-- #handlebars -->

<script id="markup" type="text/x-markup-template">
    <ul class="tweetSearchResultList">
        {{results}}
            <li>
                <img src="{{profile_image_url}}" alt="{{from_user_name}}"/>
                <p>{{text}}</p>
                <span>{{id}}</span>
                <span>{{created_at}}</span>
            </li>
        {{/results}}
    </ul>
</script><!-- #markup -->



<script>
    var templates = {
        mustache: jQuery('#mustache').html()
        , nunjucks: jQuery('#nunjucks').html()
        , dot: jQuery('#dot').html()
        , dust: jQuery('#dust').html()
        , swig: jQuery('#swig').html()
        , handlebars: jQuery('#handlebars').html()
        , markup: jQuery('#markup').html()
    };
    
</script>

Setup

var tweets;
      var template;
    
      tweets = {
        "completed_in": 0.066,
        "max_id": 253753829672239104,
        "max_id_str": "253753829672239104",
        "next_page": "?page=2&max_id=253753829672239104&q=china",
        "page": 1,
        "query": "china",
        "refresh_url": "?since_id=253753829672239104&q=china",
        "results": [{
          "created_at": "Thu, 04 Oct 2012 07:10:02 +0000",
          "from_user": "rudsonjhdw",
          "from_user_id": 129806482,
          "from_user_id_str": "129806482",
          "from_user_name": "leticia tamara da is",
          "geo": null,
          "id": 253753829672239104,
          "id_str": "253753829672239104",
          "iso_language_code": "en",
          "metadata": {
            "result_type": "recent"
          },
          "profile_image_url": "http:\/\/a0.twimg.com\/sticky\/default_profile_images\/default_profile_1_normal.png",
          "profile_image_url_https": "https:\/\/si0.twimg.com\/sticky\/default_profile_images\/default_profile_1_normal.png",
          "source": "&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;",
          "text": "The most common phrase in China \"Hey! You look familiar!\"",
          "to_user": null,
          "to_user_id": 0,
          "to_user_id_str": "0",
          "to_user_name": null
        }, {
          "created_at": "Thu, 04 Oct 2012 07:10:01 +0000",
          "from_user": "sandru3",
          "from_user_id": 63535904,
          "from_user_id_str": "63535904",
          "from_user_name": "sandruuuu!",
          "geo": null,
          "id": 253753827558313985,
          "id_str": "253753827558313985",
          "iso_language_code": "en",
          "metadata": {
            "result_type": "recent"
          },
          "profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/2663559631\/bf31e812855a0e52415880ea8e84a362_normal.jpeg",
          "profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/2663559631\/bf31e812855a0e52415880ea8e84a362_normal.jpeg",
          "source": "&lt;a href=&quot;http:\/\/www.echofon.com\/&quot;&gt;Echofon&lt;\/a&gt;",
          "text": "RT @WTA: RT @WTA: Maria Sharapova reaches the China Open QFs w\/ a 60 62 win over Polona Hercog. Awaits winner of Kerber\/Wozniacki. #WTA http:\/\/t. ...",
          "to_user": null,
          "to_user_id": 0,
          "to_user_id_str": "0",
          "to_user_name": null
        }, {
          "created_at": "Thu, 04 Oct 2012 07:10:00 +0000",
          "from_user": "BlGBlRD",
          "from_user_id": 223682306,
          "from_user_id_str": "223682306",
          "from_user_name": "Big Bird",
          "geo": null,
          "id": 253753824504864768,
          "id_str": "253753824504864768",
          "iso_language_code": "en",
          "metadata": {
            "result_type": "recent"
          },
          "profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/2678588911\/e9460b8843f561d0c4326852e9502a8a_normal.jpeg",
          "profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/2678588911\/e9460b8843f561d0c4326852e9502a8a_normal.jpeg",
          "source": "&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;",
          "text": "I better go find a safe place to hide before Mitt Romney chops me up into little pieces and sells me off to create jobs in China. :(",
          "to_user": null,
          "to_user_id": 0,
          "to_user_id_str": "0",
          "to_user_name": null
        }, {
          "created_at": "Thu, 04 Oct 2012 07:10:00 +0000",
          "from_user": "irra01010302",
          "from_user_id": 318970932,
          "from_user_id_str": "318970932",
          "from_user_name": "Lee Kyuyeon\u2665",
          "geo": null,
          "id": 253753822076342273,
          "id_str": "253753822076342273",
          "iso_language_code": "ja",
          "metadata": {
            "result_type": "recent"
          },
          "profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/2644336139\/233bd701fb824793c7bbf6638337dab5_normal.jpeg",
          "profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/2644336139\/233bd701fb824793c7bbf6638337dab5_normal.jpeg",
          "source": "&lt;a href=&quot;http:\/\/ubersocial.com&quot;&gt;UberSocial for BlackBerry&lt;\/a&gt;",
          "text": "RT _GoodbyeDays: 121002 China-Korea Music Festival #KyuMin's back  http:\/\/t.co\/dv1kF0PB --- http:\/\/t.co\/E8i5Xgv1 and *whisper** (\u25e0\ufe3f\u25e0\u2606)",
          "to_user": null,
          "to_user_id": 0,
          "to_user_id_str": "0",
          "to_user_name": null
        }, {
          "created_at": "Thu, 04 Oct 2012 07:09:59 +0000",
          "from_user": "OtherJesus",
          "from_user_id": 137240583,
          "from_user_id_str": "137240583",
          "from_user_name": "k daniels",
          "geo": null,
          "id": 253753819194855424,
          "id_str": "253753819194855424",
          "iso_language_code": "en",
          "metadata": {
            "result_type": "recent"
          },
          "profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/1270315391\/Photo_2_normal.jpg",
          "profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/1270315391\/Photo_2_normal.jpg",
          "source": "&lt;a href=&quot;http:\/\/twitter.com\/download\/iphone&quot;&gt;Twitter for iPhone&lt;\/a&gt;",
          "text": "Romney has the balls to say we need to stop borrowing money from China but the Internet is more worried about PBS.",
          "to_user": null,
          "to_user_id": 0,
          "to_user_id_str": "0",
          "to_user_name": null
        }, {
          "created_at": "Thu, 04 Oct 2012 07:09:58 +0000",
          "from_user": "s_china_2",
          "from_user_id": 191720529,
          "from_user_id_str": "191720529",
          "from_user_name": "chinatsu shiraishi",
          "geo": null,
          "id": 253753812953731073,
          "id_str": "253753812953731073",
          "iso_language_code": "ja",
          "metadata": {
            "result_type": "recent"
          },
          "profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/2517129390\/y5zchzI2_normal",
          "profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/2517129390\/y5zchzI2_normal",
          "source": "&lt;a href=&quot;http:\/\/twitter.com\/download\/android&quot;&gt;Twitter for Android&lt;\/a&gt;",
          "text": "\u3069\u3093\u306a\u4eba\u3068\u53cb\u9054\u306b\u306a\u308a\u305f\u3044\u304b\uff1f",
          "to_user": null,
          "to_user_id": 0,
          "to_user_id_str": "0",
          "to_user_name": null
        }, {
          "created_at": "Thu, 04 Oct 2012 07:09:57 +0000",
          "from_user": "DicholasNuncan",
          "from_user_id": 500352351,
          "from_user_id_str": "500352351",
          "from_user_name": "Dick Nuncan",
          "geo": null,
          "id": 253753812190367744,
          "id_str": "253753812190367744",
          "iso_language_code": "en",
          "metadata": {
            "result_type": "recent"
          },
          "profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/2587255425\/49z4wlwvqarxi8igree5_normal.jpeg",
          "profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/2587255425\/49z4wlwvqarxi8igree5_normal.jpeg",
          "source": "&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;",
          "text": "@meowitsmaija I honestly don't think we will ever pay it back. And China knows it's not wise to go to war with us over it since we run NATO",
          "to_user": "meowitsmaija",
          "to_user_id": 81961249,
          "to_user_id_str": "81961249",
          "to_user_name": "Maija Cole",
          "in_reply_to_status_id": 253753106284826624,
          "in_reply_to_status_id_str": "253753106284826624"
        }, {
          "created_at": "Thu, 04 Oct 2012 07:09:56 +0000",
          "from_user": "deerleuhan",
          "from_user_id": 320617461,
          "from_user_id_str": "320617461",
          "from_user_name": "dinyu",
          "geo": null,
          "id": 253753806930710528,
          "id_str": "253753806930710528",
          "iso_language_code": "ko",
          "metadata": {
            "result_type": "recent"
          },
          "profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/2664962425\/b4a9b1f94d85ff4ec4ef3135c01c3cbd_normal.jpeg",
          "profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/2664962425\/b4a9b1f94d85ff4ec4ef3135c01c3cbd_normal.jpeg",
          "source": "&lt;a href=&quot;http:\/\/m.dabr.co.uk&quot;&gt;Dabr&lt;\/a&gt;",
          "text": "RT @ohappybubbleo: RT @ohappybubbleo: 121002 China-Korea Festival #LUHAN - Beacuse of you, I can show you my everything.\u2764 http:\/\/t.co\/IiNzb2jl  \ub354 \ub9ce\uc740 \uc0ac\uc9c4\uc740 \uc55e\uc73c ...",
          "to_user": null,
          "to_user_id": 0,
          "to_user_id_str": "0",
          "to_user_name": null
        }, {
          "created_at": "Thu, 04 Oct 2012 07:09:55 +0000",
          "from_user": "timiacono",
          "from_user_id": 125448978,
          "from_user_id_str": "125448978",
          "from_user_name": "Tim Iacono",
          "geo": null,
          "id": 253753801322930176,
          "id_str": "253753801322930176",
          "iso_language_code": "en",
          "metadata": {
            "result_type": "recent"
          },
          "profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/1801769606\/tim_normal.jpg",
          "profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/1801769606\/tim_normal.jpg",
          "source": "&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;",
          "text": "Debt and Real Estate in China: This Washington Post story serves as a timely reminder that all is not well in Ch... http:\/\/t.co\/VNqjhCBM",
          "to_user": null,
          "to_user_id": 0,
          "to_user_id_str": "0",
          "to_user_name": null
        }, {
          "created_at": "Thu, 04 Oct 2012 07:09:54 +0000",
          "from_user": "Fhiros",
          "from_user_id": 212611036,
          "from_user_id_str": "212611036",
          "from_user_name": "The Synyster Reaper",
          "geo": null,
          "id": 253753796642107392,
          "id_str": "253753796642107392",
          "iso_language_code": "es",
          "metadata": {
            "result_type": "recent"
          },
          "profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/2444574177\/fxo62fo3d29cx60asx8c_normal.jpeg",
          "profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/2444574177\/fxo62fo3d29cx60asx8c_normal.jpeg",
          "source": "&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;",
          "text": "RT @EresCurioso: RT @EresCurioso: Matar a un oso panda en China se castiga con la muerte",
          "to_user": null,
          "to_user_id": 0,
          "to_user_id_str": "0",
          "to_user_name": null
        }, {
          "created_at": "Thu, 04 Oct 2012 07:09:53 +0000",
          "from_user": "Avatti",
          "from_user_id": 258781722,
          "from_user_id_str": "258781722",
          "from_user_name": "Avatti Consulting",
          "geo": null,
          "id": 253753793810952192,
          "id_str": "253753793810952192",
          "iso_language_code": "en",
          "metadata": {
            "result_type": "recent"
          },
          "profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/1672042358\/Avatti_Logo_Twitter_normal.png",
          "profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/1672042358\/Avatti_Logo_Twitter_normal.png",
          "source": "&lt;a href=&quot;http:\/\/twitterfeed.com&quot;&gt;twitterfeed&lt;\/a&gt;",
          "text": "PlattsOil: What impact will China and India's recent #gasoil price hikes have? Find out with Platts' Oil Roundta... http:\/\/t.co\/V6h6dEfX",
          "to_user": null,
          "to_user_id": 0,
          "to_user_id_str": "0",
          "to_user_name": null
        }, {
          "created_at": "Thu, 04 Oct 2012 07:09:53 +0000",
          "from_user": "Aishhhwarya",
          "from_user_id": 50203978,
          "from_user_id_str": "50203978",
          "from_user_name": "AISH,\u2665",
          "geo": null,
          "id": 253753792988852224,
          "id_str": "253753792988852224",
          "iso_language_code": "en",
          "metadata": {
            "result_type": "recent"
          },
          "profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/2654759049\/63d3333c33900f66c2c336c4d9090278_normal.jpeg",
          "profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/2654759049\/63d3333c33900f66c2c336c4d9090278_normal.jpeg",
          "source": "&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;",
          "text": "@Rachel__xoxo Did you watch the China episode ytd!? hahah, how was it!! :D",
          "to_user": "Rachel__xoxo",
          "to_user_id": 341290950,
          "to_user_id_str": "341290950",
          "to_user_name": "Rachel Chen"
        }, {
          "created_at": "Thu, 04 Oct 2012 07:09:50 +0000",
          "from_user": "andieacoustic",
          "from_user_id": 185732914,
          "from_user_id_str": "185732914",
          "from_user_name": "Andie Gilmore",
          "geo": null,
          "id": 253753782540828672,
          "id_str": "253753782540828672",
          "iso_language_code": "en",
          "metadata": {
            "result_type": "recent"
          },
          "profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/2672219278\/84fa38e958db77d8407d8842938d92e5_normal.jpeg",
          "profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/2672219278\/84fa38e958db77d8407d8842938d92e5_normal.jpeg",
          "source": "&lt;a href=&quot;http:\/\/twitter.com\/download\/android&quot;&gt;Twitter for Android&lt;\/a&gt;",
          "text": "Just noticed I have a bump the size of China on my leg from softball. #thatscool",
          "to_user": null,
          "to_user_id": 0,
          "to_user_id_str": "0",
          "to_user_name": null
        }, {
          "created_at": "Thu, 04 Oct 2012 07:09:49 +0000",
          "from_user": "UrbanArtists",
          "from_user_id": 37956350,
          "from_user_id_str": "37956350",
          "from_user_name": "Urban Artists",
          "geo": null,
          "id": 253753775125307393,
          "id_str": "253753775125307393",
          "iso_language_code": "en",
          "metadata": {
            "result_type": "recent"
          },
          "profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/2146140756\/picasion.com_b0b04a1faceace85bb8bf3ef722dbd23_normal.gif",
          "profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/2146140756\/picasion.com_b0b04a1faceace85bb8bf3ef722dbd23_normal.gif",
          "source": "&lt;a href=&quot;http:\/\/twitter.com\/download\/iphone&quot;&gt;Twitter for iPhone&lt;\/a&gt;",
          "text": "RT @blazeSNT: RT @blazeSNT: Trolling in china lol guangzhou city http:\/\/t.co\/dqJrVCQr",
          "to_user": null,
          "to_user_id": 0,
          "to_user_id_str": "0",
          "to_user_name": null
        }, {
          "created_at": "Thu, 04 Oct 2012 07:09:49 +0000",
          "from_user": "LuciusHu",
          "from_user_id": 786442992,
          "from_user_id_str": "786442992",
          "from_user_name": "Lucius",
          "geo": null,
          "id": 253753774479392768,
          "id_str": "253753774479392768",
          "iso_language_code": "en",
          "metadata": {
            "result_type": "recent"
          },
          "profile_image_url": "http:\/\/a0.twimg.com\/profile_images\/2562647642\/aukjnkx1ywco5oeuowsz_normal.jpeg",
          "profile_image_url_https": "https:\/\/si0.twimg.com\/profile_images\/2562647642\/aukjnkx1ywco5oeuowsz_normal.jpeg",
          "source": "&lt;a href=&quot;http:\/\/twitter.com\/tweetbutton&quot;&gt;Tweet Button&lt;\/a&gt;",
          "text": "Twitter: \u2018biggest in China\u2019, report | beyondbrics | http:\/\/t.co\/rL0q7Pu0 http:\/\/t.co\/1FIZYj2t",
          "to_user": null,
          "to_user_id": 0,
          "to_user_id_str": "0",
          "to_user_name": null
        }],
        "results_per_page": 15,
        "since_id": 0,
        "since_id_str": "0"
      };
    
      // Dust precompiled
      var dust_precomp = dust.compile(templates.dust, 'intro_precomp');
      dust.loadSource(dust_precomp);
    
      // dot precompiled
      var dot_precomp = doT.template(templates.dot);
    
      // precompile (preparse) mustache
      Mustache.parse(templates.mustache);
    
      // nunjucks precompiled
      var nunjucks_precomp = new nunjucks.Template(templates.nunjucks);
    
      // Swig precompiled
      var swig_precomp = swig.compile(templates.swig);
    
      // precompile Handlebars
      var handlebars_precomp = Handlebars.compile(templates.handlebars);

Test runner

Ready to run.

Testing in
TestOps/sec
doT
var dot_temp = doT.template(templates.dot);
var dot_res = dot_temp(tweets);
ready
mustache
Mustache.clearCache();
Mustache.render(templates.mustache, tweets);
ready
nunjucks
var tmpl = nunjucks.compile(templates.nunjucks);
tmpl.render(tweets);
ready
Swig
var swig_temp = swig.compile(templates.swig);
var swig_res = swig_temp(tweets);
ready
handlebars
var handlebars = Handlebars.compile(templates.handlebars);
handlebars(tweets);
ready
markup
var markup = Mark.up(templates.markup, tweets);
ready
dust precompiled
dust.render("intro_precomp", tweets, function() {});
ready
dot precompiled
dot_precomp(tweets);
ready
precompile (preparse) mustache
Mustache.render(templates.mustache, tweets);
ready
nunjucks precompiled
nunjucks_precomp.render(tweets);
ready
Swig precompiled
swig_precomp(tweets);
ready
precompile Handlebars
handlebars_precomp(tweets);
ready

Revisions

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