首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JavaScript:直接代码与CPS样式生成的代码性能比较

JavaScript:直接代码与CPS样式生成的代码性能比较
EN

Stack Overflow用户
提问于 2012-08-24 22:24:50
回答 2查看 582关注 0票数 2

在我的应用程序中,我正在生成JavaScript代码,它遵循CPS风格。我没有使用任何这样的延续。没有异步行为,没有暂停和恢复,也没有回调。

只是代码遵循的是编程的延拓传递方式

功能有很多阶段,每个阶段都进行处理,并将结果传递给它的继续。

我发现CPS样式代码的性能非常差。用直接样式编写的代码比CPS样式的代码快近150倍。

请检查下面的代码。

以下两种代码都相当于

代码语言:javascript
复制
var res = data.store.bookshelf.book.author;

直接样式代码:

代码语言:javascript
复制
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样式代码:

代码语言:javascript
复制
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 ms运行。

我能做些什么来改进CPS样式的代码吗?或者JavaScript本身并不适合CPS样式的代码?

以上测试是在node.js版本0.6.12上进行的。

有人能对这件事说点明白吗?

谢谢,

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-08-24 23:35:21

这种急剧放缓至少有两个潜在原因。首先,您要用动态查找替换“本机”属性查找。

只要可以,V8就会优化对象,这样访问属性就会更快。它不使用哈希表按名称查找属性,而是跟踪内部“类”,以便从已知地址查找属性。因此,data.store只是一个快速的指针比较,以确保对象是预期类型和索引指针加载。

但是,在cps_CHILD函数中,它无法进行优化,因为它不知道将提前访问哪个属性(而且每次调用它时都会发生更改)。动态查找迫使V8返回哈希表查找,这比优化的静态查找要慢。

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

票数 1
EN

Stack Overflow用户

发布于 2012-08-24 23:10:03

您应该知道,有些东西是在运行时解析的,比如在循环中输入的匿名函数。在每一个新的"i“上,将再次创建新的”构造函数“,并为每个匿名函数创建其原型。这就是为什么它变慢的原因。这是新的测试。尝试为每个匿名函数定义实际函数,在循环外嵌套它们,这将提高程序的性能。

下面是代码,它与CPS样式的代码一样深入,但只有在定义了函数之后才能实现。

代码语言:javascript
复制
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对象属性)以获得它的值。它工作得更快,因为它只需要处理内存引用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12117412

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档