奇怪, Nodejs 中 pre-compiled 的 Jade 比 pre-compiled 的 Handlebars 快?
奇怪, Nodejs 中 pre-compiled 的 Jade 比 pre-compiled 的 Handlebars 快?
Handlebars:
<p>
{{#if title}}
<h4>{{title}}</h4>
{{/if}}
{{#if list}}
{{#each list}}
<li>{{this}}</li>
{{/each}}
{{/if}}
{{#if map}}
{{#each map}}
<p>
<span>{{key}}</span>
:
<span>{{value}}</span>
</p>
{{/each}}
{{/if}}
</p>
Jade:
p
if title
h4.title= title
if list
ul
each item in list
li= item
if map
p
span= key
| :
span= value
测试代码 CoffeeScript 版本:
data =
title: 'a title'
list: [
'line a'
'line b'
'line c'
'line d'
]
map:
a: 'this is a'
b: 'this is b'
c: 'this is c'
console.time 'Handlebars'
[1..10000].map ->
Handlebars.templates['template.hbs'](data)
console.timeEnd 'Handlebars'
console.time 'jade'
[1..10000].map ->
jade.attrs data
console.timeEnd 'jade'
测试代码编译到 JS:
// Generated by CoffeeScript 1.6.3
var data, _i, _j, _results, _results1;
data = {
title: 'a title',
list: ['line a', 'line b', 'line c', 'line d'],
map: {
a: 'this is a',
b: 'this is b',
c: 'this is c'
}
};
console.time('Handlebars');
(function() {
_results = [];
for (_i = 1; _i <= 10000; _i++){ _results.push(_i); }
return _results;
}).apply(this).map(function() {
return Handlebars.templates['template.hbs'](data);
});
console.timeEnd('Handlebars');
console.time('jade');
(function() {
_results1 = [];
for (_j = 1; _j <= 10000; _j++){ _results1.push(_j); }
return _results1;
}).apply(this).map(function() {
return jade.attrs(data);
});
console.timeEnd('jade');
执行结果:
Handlebars: 301.678ms
jade: 32.990ms
代码备份在 Github 上:
https://github.com/jiyinyiyong/jade-test
在线的版本在这里:
http://s.jiyinyiyong.info/jade-test/index.html
是不是我写的有错误的? 这个结果看起来好别扭…
奇怪,Node.js 中 pre-compiled 的 Jade 比 pre-compiled 的 Handlebars 快?
背景
在模板引擎中,Jade(现在称为Pug)和Handlebars都是非常流行的选项。两者都提供了预编译功能,这可以提高性能。然而,在进行了一些基准测试之后,发现Jade的性能明显优于Handlebars。
示例代码
我们来看一下两个模板引擎的代码示例:
Handlebars 模板
<p>
{{#if title}}
<h4>{{title}}</h4>
{{/if}}
{{#if list}}
{{#each list}}
<li>{{this}}</li>
{{/each}}
{{/if}}
{{#if map}}
{{#each map}}
<p>
<span>{{key}}</span>:
<span>{{value}}</span>
</p>
{{/each}}
{{/if}}
</p>
Jade (Pug) 模板
p
if title
h4.title= title
if list
ul
each item in list
li= item
if map
p
span= key
| :
span= value
测试代码
为了比较两者的性能,我们使用了CoffeeScript编写了一个简单的测试脚本,并将其编译为JavaScript:
CoffeeScript 版本
data =
title: 'a title'
list: [
'line a'
'line b'
'line c'
'line d'
]
map:
a: 'this is a'
b: 'this is b'
c: 'this is c'
console.time 'Handlebars'
[1..10000].map ->
Handlebars.templates['template.hbs'](data)
console.timeEnd 'Handlebars'
console.time 'jade'
[1..10000].map ->
jade.compileClient()(data)
console.timeEnd 'jade'
编译后的 JavaScript 版本
// Generated by CoffeeScript 1.6.3
var data, _i, _j, _results, _results1;
data = {
title: 'a title',
list: ['line a', 'line b', 'line c', 'line d'],
map: {
a: 'this is a',
b: 'this is b',
c: 'this is c'
}
};
console.time('Handlebars');
(function() {
_results = [];
for (_i = 1; _i <= 10000; _i++) { _results.push(_i); }
return _results;
}).apply(this).map(function() {
return Handlebars.templates['template.hbs'](data);
});
console.timeEnd('Handlebars');
console.time('jade');
(function() {
_results1 = [];
for (_j = 1; _j <= 10000; _j++) { _results1.push(_j); }
return _results1;
}).apply(this).map(function() {
return jade.compileClient()(data);
});
console.timeEnd('jade');
执行结果
运行上述测试代码后,得到的结果如下:
Handlebars: 301.678ms
jade: 32.990ms
分析
从测试结果可以看出,Jade的性能显著优于Handlebars。这可能是因为以下几个原因:
- 语法简洁性:Jade的语法更为简洁,减少了模板中的冗余符号,从而提高了解析效率。
- 编译优化:Jade在编译阶段可能进行了更多的优化,使得生成的渲染函数更高效。
- 逻辑处理:Handlebars中的
if
和each
指令可能需要更多的条件判断,而Jade的逻辑处理则更为直接。
结论
虽然测试结果可能受到多种因素的影响,但根据上述测试代码和结果,Jade在性能上确实比Handlebars更优。如果您在项目中需要高性能的模板渲染,可以考虑使用Jade(Pug)。
沉了啊… 我的测试写得太简单了些, 有没有给强化一下的?
从你提供的测试代码和结果来看,Jade(现在更名为Pug)在性能上确实优于Handlebars。这可能是因为Jade的设计更倾向于生成高效的JavaScript代码,并且其语法更加简洁,使得模板编译后的代码执行速度更快。
以下是一些可能的原因和建议:
1. 简洁的语法
Jade的语法更加简洁,减少了不必要的HTML标签嵌套和属性,这使得编译后的代码更高效。
2. 编译优化
Pug(Jade的后续版本)对模板编译进行了优化,生成的JavaScript代码执行效率更高。
3. 语法解析
Jade的语法解析过程更简单,因为它的语法更加直接和明确,这减少了运行时的解析成本。
示例代码
为了更好地理解这种差异,可以比较两个模板的编译后代码。这里提供一个简单的示例:
Handlebars 模板
<p>
{{#if title}}
<h4>{{title}}</h4>
{{/if}}
{{#if list}}
<ul>
{{#each list}}
<li>{{this}}</li>
{{/each}}
</ul>
{{/if}}
{{#if map}}
{{#each map}}
<p>
<span>{{key}}</span> : <span>{{value}}</span>
</p>
{{/each}}
{{/if}}
</p>
Pug 模板
p
if title
h4.title= title
if list
ul
each item in list
li= item
if map
p
span= key
| :
span= value
测试代码
以下是测试代码的简化版,使用Node.js环境进行测试:
const Handlebars = require('handlebars');
const fs = require('fs');
const jade = require('jade');
const data = {
title: 'a title',
list: ['line a', 'line b', 'line c', 'line d'],
map: { a: 'this is a', b: 'this is b', c: 'this is c' }
};
// Compile Handlebars template
const handlebarsTemplate = fs.readFileSync('template.hbs', 'utf8');
const compiledHandlebars = Handlebars.compile(handlebarsTemplate);
// Compile Jade template
const jadeTemplate = jade.compile(fs.readFileSync('template.pug', 'utf8'));
const compiledJade = jadeTemplate();
console.time('Handlebars');
for (let i = 0; i < 10000; i++) {
compiledHandlebars(data);
}
console.timeEnd('Handlebars');
console.time('Jade');
for (let i = 0; i < 10000; i++) {
compiledJade(data);
}
console.timeEnd('Jade');
通过上述测试,你可以看到Jade在性能上的优势。如果你发现你的代码有问题或有其他疑问,欢迎进一步讨论。