精品 让 ejs 更加快 | Let ejs faster with `options._with = false`
 发布于 12 年前  作者 fengmk2  16378 次预览  最后一次回复是 10 年前  来自 分享 

今天看 ejs 源代码的时候,发现 with 是可以设置为 false 的。 根据 从tenjin到nTenjin的几点性能优化方法 的优化经验, 不使用 with 会有很大的性能提高。

ejs 普通版使用方式

默认地,ejs 都会开启 with 模式:

var TPL_WITH_TRUE = '\
<% if (user) { %>\
  <h2>with_true: <%= user.name %></h2>\
<% } %>';

var render = ejs.compile(TPL_WITH_TRUE);
var s = render({user: {name: 'fengmk2'}});
console.log('_with: true', s);

options._with = false 强制关闭 with 模式

var TPL_WITH_FALSE = '\
<% if (locals.user) { %>\
  <h2>with_false: <%= locals.user.name %></h2>\
<% } %>';

var render = ejs.compile(TPL_WITH_FALSE, {_with: false});
var s = render({user: {name: 'fengmk2'}});
console.log('_with: false', s);

对比 ejs 生成的两个模板方法

  • 开启 with
try {
var buf = [];
with (locals || {}) { (function(){ 
 buf.push('');__stack.lineno=1; if (user) { ; buf.push('  <h2>with_true: ', escape((__stack.lineno=1,  user.name )), '</h2>');__stack.lineno=1; } ; buf.push(''); })();
} 
return buf.join('');
} catch (err) {
  rethrow(err, __stack.input, __stack.filename, __stack.lineno);
}
  • 关闭 with
try {
var buf = [];
 buf.push('');__stack.lineno=1; if (locals.user) { ; buf.push('  <h2>with_false: ', escape((__stack.lineno=1,  locals.user.name )), '</h2>');__stack.lineno=1; } ; buf.push('');
return buf.join('');
} catch (err) {
  rethrow(err, __stack.input, __stack.filename, __stack.lineno);
}

Benchmark 性能测试

通过 options_with.js 的测试结果可以看到, 不使用 with 差不多有 4X 的性能提高。

使用 {_with: false} 性能就提高了!就这么简单!

$ node options_with.js

_with: false   <h2>with_false: fengmk2</h2>
_with: true   <h2>with_true: fengmk2</h2>
options._with = false x 821,470 ops/sec ±3.55% (85 runs sampled)
options._with = true x 268,084 ops/sec ±7.05% (87 runs sampled)
Fastest is options._with = false

有爱

^_^ 希望本文对你有用。

原文: http://fengmk2.github.io/benchmark/ejs/with_false_better_than_true.html

18 回复
udbmnm

今天在http://ectjs.com/看到模板引擎性能对比没使用with速度快了不少

pengchun

把模板编译成静态函数靠不靠谱?

robertlyc

自从写了jade之后看到<% %> 就头晕目眩

fengmk2

如果你的模板文件是动态更新的,那么就需要重新编译一次。

pengchun

@suqian 模板文件有动态更新的么?或者说在可控的频率下这个貌似靠谱的

DoubleSpout

suqian大大文章看了果然收益啊~学习了

youxiachai

我想弱弱的问一下…这个with 的作用是?

fengmk2

@pengchun 更新模板的适合删除cache就ok了。

fengmk2

我的都是基础性的,看你的都是高深啊

DoubleSpout

@suqian 你发的都是实用性文章,我写的都是花拳绣腿,忽悠忽悠人的。。

youxiachai

@suqian 好神奇的语法…话说,不推荐使用吗…为什么作者默认开启呢…

fengmk2

@youxiachai 不使用with,你的模板就需要到处 locals.xxx

alsotang

@suqian 印象中有一次看一篇讲 V8 的文章,也说到 with 是优化难点

yzhangpan

@youxiachai hi哥们能给说一下ejs,opction;catch:参数怎么用吗,如何做到缓存的缓存存到了那一块了!

alsotang

今天重新测试了一下 https://github.com/fengmk2/fengmk2.github.com/blob/master/benchmark/ejs/options_with.js 的性能 环境 node v2.3.0, v8 4.2.77.20

结果:

_with: false   <h2>with_false: fengmk2</h2>
_with: true   <h2>with_true: fengmk2</h2>
options._with = false x 336,185 ops/sec ±1.80% (83 runs sampled)
options._with = true x 249,998 ops/sec ±1.27% (87 runs sampled)
Fastest is options._with = false
alsotang

_with: false 的结果竟然比帖子里的慢那么多,好奇怪。可能 ejs 版本不同了。