JavaScript:直接代码与CPS风格的生成代码性能比较

在我的应用程序中,我正在生成遵循CPS风格的JavaScript代码。 我不是“使用任何”延续“。 没有asynchronous行为,没有暂停和恢复,没有callback。

只是代码是继续传递编程的风格 。

function有很多阶段,每个阶段都进行处理,并将结果传递给其继续。

我发现CPS样式代码的性能很差。 以直接风格编写的代码比CPS样式代码快150倍。

请检查下面的代码。
下面的代码都相当于

var res = data.store.bookshelf.book.author; 

直接式样代码:

 var data = { store : { bookshelf : {book : {author:"Douglas Crockford"}}}}; var t1 = new Date().getTime(); for(var i = 0; i < 1000*1000*100; i+=1){ var temp0 = data; var temp1 = temp0.store; var temp2 = temp1.bookshelf; var temp3 = temp2.book; var temp4 = temp3.author; var res = temp4; } var t2 = new Date().getTime(); console.log(t2-t1); 

上面的代码几乎运行了95毫秒。

CPS样式代码:

 var data = { store : { bookshelf : {book : {author:"Douglas Crockford"}}}}; // return the variable to the continuation function cps_VARREF(x,f){ return f(x); } // get the value of the property from the variable and pass it to the continuation function cps_CHILD(x,child,f){ return f(x[child]); } // simply return the input value, essentially closing the continuation chain function ret_(x){ return x; } var t1 = new Date().getTime(); for(var i = 0; i < 1000*1000*100; i+=1){ var res = function(c_){ return cps_VARREF(data,function(x1){ return cps_CHILD(x1,"store",function(x2){ return cps_CHILD(x2,"bookshelf",function(x3){ return cps_CHILD(x3,"book",function(x4){ return cps_CHILD(x4,"author",c_);});});});});}(ret_); } var t2 = new Date().getTime(); console.log(t2-t1); 

上述CPS风格的代码运行在15000毫秒

有什么我可以做的改善CPS风格的代码? 或JavaScript本质上不适合CPS风格的代码?

上面的testing是在node.js版本0.6.12上完成的

有人可以在这个问题上抛出一些光?

谢谢,

经济增长放缓至less有两个潜在的原因。 首先是你用dynamic查找replace“本地”属性查找。

V8会尽可能优化对象,以便访问属性更快。 它不使用散列表来查找属性,而是跟踪内部“类”,以便从已知地址查找属性。 所以data.store只是一个快速指针比较,以确保对象是预期的types和索引的指针加载。

cps_CHILD函数中,它不能做这样的优化,因为它不知道什么属性会被提前访问(每次调用它时都会改变)。 dynamic查找强制V8回退到哈希表查找,这比优化的静态查找慢。

另一个问题是函数调用的开销。 每次嵌套的函数每次传递到下一个函数时都必须重新创build。 它们不需要每次编译,但仍需要在新的上下文中创build。

你应该知道有些东西在运行时被parsing,就像你在循环中input的匿名函数一样。 在每个新的“我”再次创build新的“构造函数”和它的每个anonymus函数的原型。 这就是为什么它慢。 这是新的testing。 尝试为每个匿名函数定义实际函数,将它们嵌套在循环之外,这应该提高程序的性能。

这里是代码,它深入到你的CPS风格的代码,但只有一次函数定义

 var data = { store : { bookshelf : {book : {author:"Douglas Crockford"}}}}; function getValueFrom(data){ return data; } function getAuthorFrom(data){ return getValueFrom(data); } function getBookFrom(data){ return getAuthorFrom(data["book"]); } function getBookShelfFrom(data){ return getBookFrom(data["bookshelf"]); } function getStoreFrom(data){ return getBookShelfFrom(data["store"]); } function getAuthor(data){ return getAuthor(data); } var t1 = new Date().getTime(); for(var i = 0; i < 1000*1000*100; i+=1){ var res = getStoreFrom(data); } var t2 = new Date().getTime(); console.log(t2-t1); 

它运行速度快4-5倍。 由于JS引擎需要寻找函数原型,所以它还是比较慢,所以可以放在堆上执行。 在你的第一种情况下(非CSP风格),当你使用点访问属性JS引擎只查询哈希按键(JS对象属性)来获得它的价值。 它工作得更快,因为它只需要处理内存引用。

Interesting Posts