aimingoo的专栏

.F{color:red}aimingoo

用户操作
[即时聊天] [发私信] [加为好友]
周爱民ID:aimingoo
408866次访问,排名123好友89人,关注者131
aimingoo的文章
原创 121 篇
翻译 0 篇
转载 0 篇
评论 706 篇
aimingoo的公告
新书出版:
china-pub在线购买
相关评论和文章

其它:
 相关评论和文章
 相关评论和文章
最近评论
cloudgamer:这篇真的很深入啊
佩服
sherryxuelian:读了《大道至简》,感觉真的收益匪浅。我对这本书的评价是:作者真的是一个善于深刻思考的人,这本书透过繁杂的技术神秘面纱,引领读者来到一个简单和纯净的本源之所,在这里,我看到我曾迷信着的,在纷乱中困惑着的,竟是如此的真实,合理和亲切。再次感谢作者提出对《移山之道》的建议,正好我也买了这本书,呵呵,其实还真是因为《大道至简》才买的,刚开始看书名还以为是《大道至简》的仿照版,(还在想微软这么资深的员……
jackhatedance:这个标题使我想到了martin fowler的blog,他说的是更直接:UML无用。作为敏捷的先锋,他认为MDA,UML都是没用的,DSL才是正道。他说敏捷团队基本不用UML。我想是因为他到了更高的境界,UML图已经可以在他的脑袋里画了。

链接如下:
http://martinfowler.com/bliki/ModelDrivenSoftwareDevelo……
cm_chenmin:老师的文章必定是掘地三尺呀
uvsjoh:看来我是成不了大师啊 ^_^, 那些算法、数学真难懂!
文章分类
收藏
    相册
    旅游
    我、joy与朋友们
    其它
    Hello World!
    ZDNet China软件技术专区
    我的链接
    aimingoo's 网上空地
    我的Delphi项目资源
    麦秸的垛
    我的朋友们
    kiki-玩java的国际游人
    Margaret
    叶卡-Online
    左左-网行者
    老孟-孟岩的孟
    存档
    订阅我的博客
    XML聚合  FeedSky

    原创 JavaScript全局优化带来的负面效果……收藏

    新一篇: QoBean的元语言系统(一) | 旧一篇: 对JavaScript的eval()中使用函数的进一步讨论~

    读者在China-pub中指出《JavaScript语言精髓与编程实践》的一个示例在FF上不正常。具体来说,就是第“4.6.6  语句或语句块中的闭包问题”中的第二、三、四三个示例。这个问题我反复测试过,只出现FireFox(SpiderMonkey JavaScript)中。我当时意识到是SpiderMonkey特殊的全局变量引用机制导致的,但因为没有切实地、在源代码级别观察过,因此我没有立即回答这个问题。

    这些天有点时间了,把这个话题拿出来重新讨论。代码是这样子的:

    --------
    var obj = new Object();
    var events = {m1: "clicked", m2: "changed"};
    
    for (e in events) {
       obj[e] = function(){
          alert(events[e]);
       };
    }
    // 显示false, 表明是不同的函数实例
    alert( obj.m1 === obj.m2 );
    --------

    这个示例在其它的js引擎中,总是显示false。这与我们在“4.6.6”章中的分析是一致的。但是在Firefox中,就会显示true。按照我们的分析,这里的匿名函数直接量应该根据循环次数创建多个实例。然而在Firefox中,它只创建了一次。

    出了什么问题了?

    回到SpiderMonkey JavaScript引擎的源代码中,我们得知道,执行引擎并不直接执行代码,而是先将代码文本分析(parser)成代码树,再按规则执行代码树中的指令结点(op)。指令在JS中总是确定的,例如源代码中是FOR,那么总是JSOP_FOR*这个操作码。但是,指令所使用的参数却不是确定的,而是通过参数名绑定到一个具体的操作数。参数名是字符串,也就是标识符;操作数则位于该代码上下文所使用的栈中。这个栈中的操作数使用slot位置来表示。因此,这个关键的函数就是BindNameToSlot()。
    这个函数具体分析执行过程中使用的一个标识符应该绑定到那个闭包(上下文)中的哪个slot位置。这受非常多的因素影响,例如我们下面这段代码(出自“5.2.3  奇特的、甚至是负面的影响”):

    --------
    var i = 100;
    function myFunc(ctx) {
      alert("value is: " + i);
      eval(ctx);
      alert("value is: " + i);
    }
    --------

    在myFunc()中,由于有一行动态执行eval()的代码,因此第一行和第二行中的变量“i”,就可能被绑定在不同闭包的solt上。例如我们执行:

    --------
    myFunc("var i = 10;");
    --------

    那么代码的执行效果将是显示:

    --------
    value is: 100
    value is: 10
    --------

    这也就意味着变量名必须在每行代码执行时都重新绑定——而这,也正是JavaScript效率偏低的原因。

    这些过程,对所有的JS引擎来说是统一的,这是语言规范所决定的。然而,SpiderMonkey大概是觉得这想在全局范围上的效率太差……准确地说,如果一个变量标识符总是要绑定到全局变量,而每次绑定都要回溯很多层次的闭包链,所以从效率上来讲,每次都这样做就会很不经济。

    于是SpiderMonkey做了一个优化。这个优化在SpiderMonkey中叫“optimizeGlobal”。其规则是:

    1、在语法分析期(jsparse.c)对标识符进行计数

                    /* Measure optimizable global variable uses. */
                    ATOM_LIST_SEARCH(ale, &tc->decls, pn->pn_atom);
                    if (……
                        js_IsGlobalReference(tc, pn->pn_atom, &loopy)) {
                        tc->globalUses++;
                        if (loopy)
                            tc->loopyGlobalUses++;
                    }

    也就是说,当一个标识符是引用全局的,则globalUses加1,而当它处于循环体内(loopy)时,loopyGlobalUses也同时加1。


    2、在标识符绑定时(BindNameToSlot)确定是否优化,即启用optimizeGlobal

    function BindNameToSlot(...) {
    ...
            optimizeGlobals = (tc->globalUses >= 100 ||
                               (tc->loopyGlobalUses &&
                                tc->loopyGlobalUses >= tc->globalUses / 2));
    ...
    }

    也就是说,在一个代码块中有超过100个全局变量名的引用;或在循环中引用全局变量的数量,超过了该上下文中所引用全局变量数量的1/2。则开启optimizeGlobal……


    3、当启用optimizeGlobal时的一些优化效果
    --------
    这个就不讲了……极复杂的一套规则,其中就包括本文前面我们提到的这个问题。


    OK。到这里我们告一段落。基本上来说,从这个例子的实际效果来讲,这是一个失败的优化。或者说SpiderMonkey中存在这样的BUG。在书中“4.6.6  语句或语句块中的闭包问题”中的第二、三、四三个示例,仅在SpiderMonkey中存在异常,就证明了这一点。另一方面,我们可以将示例代码稍作一下修改,改变它的上下文环境,效果就大为不同了。例如:

    var obj = new Object();
    var events = {m1: "clicked", m2: "changed"};
    
    with ({}) { // <-- 打开一个对象闭包
      for (e in events) {
       obj[e] = function(){
        alert(events[e]);
       }
      }
    }
    
    // 显示false, 表明是不同的函数实例
    alert( obj.m1 === obj.m2 );


    发表于 @ 2008年07月23日 22:38:00|评论(loading...)|编辑|收藏

    新一篇: QoBean的元语言系统(一) | 旧一篇: 对JavaScript的eval()中使用函数的进一步讨论~

    评论

    #hgk 发表于2008-07-24 23:34:20  IP: 61.51.89.*
    我平时一般练习喜欢用Web的Javascript Shell,http://www.squarefree.com/shell/ ,很方便好用。但周老师书中的个别例子在web shell和直接在FF中有差别。此文第一个例子直接在FF中为true,而在FF的shell中为false。
    我觉得通过在浏览器中以javascript模拟的javascript shell,是无法在完全和javascript一致的。
    #xingqiliudehuanghun 发表于2008-07-25 09:57:44  IP: 219.142.59.*
    周老师,正在拜读你的大作,还没有读到这一部分,我在自己的firefox3下运行了代码发现结果是false并不是true,不知道您是在那个版本的firefox下运行的
    #Jeltter 发表于2008-07-25 13:54:13  IP: 60.12.235.*
    非常赞的研究精神
    #Linster_ck 发表于2008-07-25 17:11:25  IP: 125.34.52.*
    js 里 三个等号 是什么意思
    我没这么用过
    谁解释下
    #wlkjhxd 发表于2008-07-25 23:31:15  IP: 58.61.221.*
    1=="1";//返回true
    1==="1";//返回false
    #MasDn 发表于2008-07-26 12:24:13  IP: 58.25.172.*
    === 是指完全相等
    在常量情况下 是指类型和值都一样的相等.

    在对象 object情况下 是指同一个对象
    #bcrun 发表于2008-07-28 09:15:08  IP: 118.249.100.*
    唉,我的2.0.0.16上看同样是false,作为鼎鼎大名的周老师,写这种文章竟然不写明版本号,实在让人失望,看了下这篇文章的发表日期“发表于 @ 2008年07月23日 22:38:00”,才过去几天而已,
    #aimingoo 发表于2008-07-28 11:28:59  IP: 125.33.144.*
    这个这个~~ 楼上不必这样讲话的哇。

    我手上正用的版本是2.0.0.12,显示true;
    我安装使用正式发布的3.0,显示true;
    我在写文档过程中测试的也是上述版本。

    我刚才更新了版本2.0.0.16,显示true。

    事实上,应该注意的是,这个DEMO涉及到SpiderMonkey引擎在全局闭包中的一些优化特性,因此hgk说它喜欢使用的Web Shell,就可能因为代码不运行在全局而出现不一致的情况。

    我写文章时所阅读的代码,是从mozilla的官方FTP中下载的最新版本的SpiderMonkey。而且事实上从FF2到FF3,这个核心都没有变化过,因此应该是没有差异的。至于上述出现差异的情况,应当是测试方法的问题。

    测试方法很简单,创建一个普通的文本文件,命名为1.html,然后将示例代码复制进去,前后加上一对<script></script>标签。然后用ff打开,OK,看答案。
    #goForIdeal 发表于2008-07-30 00:30:28  IP: 125.114.8.*
    同事刚购了周老师的《JavaScript语言精髓与编程实践》,从你的PPT中早就窥见了该书的特色,先随便翻了一下,感觉很开阔视野,值得研究。
    #xingqiliudehuanghun 发表于2008-07-30 21:33:11  IP: 123.116.102.*
    确实如此,除读文章的时候为了偷懒直接在firebug下运行的
    ,显示的是false,在文件中运行显示true。周老师的书是我目前找到的最好的一本,另一本是大砖头似的权威指南,不过老外写的书看起来总是感觉很别扭
    #forxm1972 发表于2008-08-20 16:14:08  IP: 119.123.9.*
    根据ECMA-262 3rd/13.1.1 Equated Grammar Productions之第1点, 此文第1个例子, firefox的处理似乎是对的, 而ie的处理是错的, 与全局优化没有关系
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © aimingoo