Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
148 changes: 95 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,95 +15,137 @@
- [Jade](https://github.com/visionmedia/jade) v0.28.1 ([website](http://jade-lang.com/))
- [Swig](https://github.com/paularmstrong/swig) v0.13.5
- [Underscore](https://github.com/documentcloud/underscore) v1.4.4 ([website](http://underscorejs.org/))
- [Nunjucks](https://github.com/mozilla/nunjucks) v3.0.0 ([website](https://mozilla.github.io/nunjucks/))
- [Vash](https://github.com/kirbysayshi/vash) v0.12.2 ([website](https://github.com/kirbysayshi/vash/))
- [Mustache](https://github.com/janl/mustache.js) v2.3.0 ([website](https://github.com/janl/mustache.js/))
- [Pug](https://github.com/pugjs/pug) v2.0.0-beta6 ([website](https://pugjs.org/api/getting-started.html))

## Test environment

- CPU: Intel Core i5 450M 2.4Ghz
- OS: Ubuntu Server 12.04
- Node.JS version: 0.8.21
- CPU: Intel Core i5 4690 3.50Ghz
- OS: Windows 10
- Node.JS version: v6.5.0

## Performance Report
Gaikan ( 1370ms) - fastest
Fest ( 1679ms) - 23% slower
doT ( 2106ms) - 54% slower
ECT ( 2864ms) - 109% slower
Pug ( 3212ms) - 134% slower
Vash ( 3311ms) - 142% slower
Underscore ( 3737ms) - 173% slower
Dust ( 3777ms) - 176% slower
Hogan.js ( 3789ms) - 177% slower
EJS without `with` ( 4293ms) - 213% slower
Handlebars.js ( 4442ms) - 224% slower
Swig ( 5755ms) - 320% slower
Mustache ( 5775ms) - 322% slower
Nunjucks ( 6329ms) - 362% slower
Jade without `with` ( 6988ms) - 410% slower
Eco ( 7570ms) - 453% slower
EJS ( 8180ms) - 497% slower
CoffeeKup ( 8514ms) - 521% slower
Jade (18966ms) - 1284% slower

## Results

Rendering 100000 templates:
Pug
Escaped : 3095ms
Unescaped : 117ms
Total : 3212ms

Nunjucks
Escaped : 3177ms
Unescaped : 3152ms
Total : 6329ms

Vash
Escaped : 2463ms
Unescaped : 848ms
Total : 3311ms

Mustache
Escaped : 3708ms
Unescaped : 2067ms
Total : 5775ms

ECT
Escaped : 2180ms
Unescaped : 133ms
Total : 2313ms
Escaped : 2775ms
Unescaped : 89ms
Total : 2864ms

Gaikan
Escaped : 1318ms
Unescaped : 52ms
Total : 1370ms

Dust
Escaped : 2547ms
Unescaped : 363ms
Total : 2910ms
Escaped : 3462ms
Unescaped : 315ms
Total : 3777ms

Hogan.js
Escaped : 3252ms
Unescaped : 758ms
Total : 4010ms

Gaikan
Escaped : 4288ms
Unescaped : 85ms
Total : 4373ms
Escaped : 3455ms
Unescaped : 334ms
Total : 3789ms

Fest
Escaped : 4179ms
Unescaped : 265ms
Total : 4444ms
Escaped : 1448ms
Unescaped : 231ms
Total : 1679ms

EJS without `with`
Escaped : 4526ms
Unescaped : 485ms
Total : 5011ms
Escaped : 3930ms
Unescaped : 363ms
Total : 4293ms

doT
Escaped : 5329ms
Unescaped : 82ms
Total : 5411ms
Escaped : 2038ms
Unescaped : 68ms
Total : 2106ms

Swig
Escaped : 5020ms
Unescaped : 407ms
Total : 5427ms
Escaped : 5488ms
Unescaped : 267ms
Total : 5755ms

Underscore
Escaped : 5775ms
Unescaped : 2486ms
Total : 8261ms
Escaped : 2549ms
Unescaped : 1188ms
Total : 3737ms

Eco
Escaped : 8512ms
Unescaped : 991ms
Total : 9503ms
Escaped : 6942ms
Unescaped : 628ms
Total : 7570ms

EJS
Escaped : 6316ms
Unescaped : 2734ms
Total : 9050ms
Escaped : 6118ms
Unescaped : 2062ms
Total : 8180ms

Handlebars.js
Escaped : 7815ms
Unescaped : 2573ms
Total : 10388ms
Escaped : 3007ms
Unescaped : 1435ms
Total : 4442ms

Jade without `with`
Escaped : 8566ms
Unescaped : 2982ms
Total : 11548ms
Escaped : 5482ms
Unescaped : 1506ms
Total : 6988ms

CoffeeKup
Escaped : 4968ms
Unescaped : 9983ms
Total : 14951ms
Escaped : 2294ms
Unescaped : 6220ms
Total : 8514ms

Jade
Escaped : 18330ms
Unescaped : 12095ms
Total : 30425ms
Escaped : 11757ms
Unescaped : 7209ms
Total : 18966ms

## Usage

git clone git://github.com/baryshev/template-benchmark.git
git clone https://github.com/minicacristi/template-benchmark.git
cd template-benchmark
npm install
node ./benchmark.js
41 changes: 38 additions & 3 deletions benchmark.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ var handlebars = require('./handlebars/handlebars.js');
var coffeekup = require('./coffeekup/coffeekup.js');
var underscore = require('./underscore/underscore.js');
var gaikan = require('./gaikan/gaikan.js');
var mustache = require('./mustache/mustache.js');
var vash = require('./vash/vash.js');
var nunjucks = require('./nunjucks/nunjucks.js');
var pug = require('./pug/pug.js');

var test = function(name, sample, cb) {
var i = 0;
Expand Down Expand Up @@ -59,19 +63,29 @@ var samples = [
{ name : 'CoffeeKup', sample : coffeekup },
{ name : 'Jade without `with`', sample : jadeWithoutWith },
{ name : 'Handlebars.js', sample : handlebars },
{ name : 'Eco', sample : eco },
{ name : 'EJS', sample : ejs },
{ name : 'Eco', sample : eco },
{ name : 'Underscore', sample : underscore },
{ name : 'Swig', sample : swig },
{ name : 'doT', sample : dot },
{ name : 'EJS without `with`', sample : ejsWithoutWith },
{ name : 'Fest', sample : fest },
{ name : 'Gaikan', sample: gaikan },
{ name : 'Hogan.js', sample : hogan },
{ name : 'Dust', sample : dust },
{ name : 'ECT', sample : ect }
{ name : 'Gaikan', sample: gaikan },
{ name : 'ECT', sample : ect },
{ name : 'Mustache', sample : mustache },
{ name : 'Vash', sample : vash },
{ name : 'Nunjucks', sample : nunjucks },
{ name : 'Pug', sample : pug },
];

var results = [];
var pad = function (val, num, pre) {
val = typeof val === 'string' ? val : '' + val;
while (val.length < num) val = (pre ? ' ' : '') + val + (pre ? '' : ' ');
return val;
};
var runTests = function () {
if (samples.length) {
var sample = samples.pop();
Expand All @@ -82,9 +96,30 @@ var runTests = function () {
console.log(' Unescaped : ' + resultUnescaped + 'ms');
console.log(' Total : ' + (result + resultUnescaped) + 'ms');
console.log('');
results.push({
name: name,
escaped: result,
unescaped: resultUnescaped,
total: result + resultUnescaped
});
runTests();
});
});
} else {
console.log('Performance report for ' + count + ' templates (' + process.platform + '):\n');
results.sort(function (a, b) {
var x = a.total;
var y = b.total;
return x < y ? -1 : (x > y ? 1 : 0);
});
var fastest = results[0].total;
for (var i = 0; i < results.length; i += 1) {
var result = results[i];
var percentage = Math.round((100 / fastest * result.total) - 100);
console.log(pad(result.name, 20) +
' (' + pad(result.total, 5, true) + 'ms)' +
(i == 0 ? ' - fastest' : ' - ' + percentage + '% slower'));
}
}
};

Expand Down
19 changes: 11 additions & 8 deletions gaikan/gaikan.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
'use strict';
var gaikan = require('gaikan');
var compiled;
var tplData;

gaikan.options.directories = ['gaikan'];

module.exports.prepare = function (data, done) {
tplData = data;
compiled = gaikan.compileFile('tpl_escaped', 'gaikan', undefined, true);
done();
tplData = data;
compiled = gaikan.compileFromFile('tpl_escaped');
done();
};

module.exports.prepareUnescaped = function (data, done) {
tplData = data;
compiled = gaikan.compileFile('tpl_unescaped', 'gaikan', undefined, true);
done();
tplData = data;
compiled = gaikan.compileFromFile('tpl_unescaped');
done();
};

module.exports.step = function (done) {
var html = compiled(tplData);
done(undefined, html);
var html = compiled(gaikan, tplData);
done(undefined, html);
};
18 changes: 9 additions & 9 deletions gaikan/tpl_escaped.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<html>
<head>
<title>#{data.title}</title>
<title>#{root.title}</title>
</head>
<body>
<p>#{data.text}</p>
<ins data-for="data.projects">
<a href="#{data.url}">#{data.name}</a>
<p>#{data.description}</p>
</ins>
<ins data-if="!data.projects">
<p>#{root.text}</p>
<div data-for="project in root.projects" data-extract>
<a href="#{project.url}">#{project.name}</a>
<p>#{project.description}</p>
</div>
<div data-if="!root.projects.length" data-extract>
No projects
</ins>
</div>
</body>
</html>
</html>
18 changes: 9 additions & 9 deletions gaikan/tpl_unescaped.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<html>
<head>
<title>!{data.title}</title>
<title>!{root.title}</title>
</head>
<body>
<p>!{data.text}</p>
<ins data-for="data.projects">
<a href="!{data.url}">!{data.name}</a>
<p>!{data.description}</p>
</ins>
<ins data-if="!data.projects">
<p>!{root.text}</p>
<div data-for="project in root.projects" data-extract>
<a href="!{project.url}">!{project.name}</a>
<p>!{project.description}</p>
</div>
<div data-if="!root.projects.length" data-extract>
No projects
</ins>
</div>
</body>
</html>
</html>
23 changes: 23 additions & 0 deletions mustache/mustache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
var fs = require('fs');
var mustache = require('mustache');
var tpl;
var tplData;

var view = {};

module.exports.prepare = function (data, done) {
tpl = fs.readFileSync(__dirname + '/tpl_escaped.mustache', 'utf8');
tplData = data;
done();
};

module.exports.prepareUnescaped = function (data, done) {
tpl = fs.readFileSync(__dirname + '/tpl_unescaped.mustache', 'utf8');
tplData = data;
done();
};

module.exports.step = function (done) {
var html = mustache.render(tpl, tplData);
done(undefined, html);
};
16 changes: 16 additions & 0 deletions mustache/tpl_escaped.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<html>
<head>
<title>{{{title}}}</title>
</head>
<body>
<p>{{text}}s</p>
{{#projects}}
<a href={{url}}>{{name}}</a>
<p>{{description}}</p>
{{/projects}}
{{^projects}}
No projects
{{/projects}}
</body>
</html>
Loading