`
wjlgryx
  • 浏览: 306784 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

 JavaScript分析

阅读更多

4.3 JavaScript分析

随着客户端应用程序越来越复杂,对JavaScript进行分析的需求渐渐显露。当通过大量函数调用和对象交互来生成复杂的用户界面时,要找出影响程序性能的问题来源也变得困难起来。分析脚本不仅能够从脚本优化中排除主观臆断因素,而且还能让人们了解程序运行时的细节,以及给定时间段内所执行的函数调用次数。

开发人员在开始编写代码时,通常都倾向于在有效代码和有效编码之间采用折衷方案。而为了清晰起见,对代码的评估应该采用最短有效路线,同时花最少时间去编写代码。但是,这样一来,降低效率的因素将不可避免地侵入代码,无论开发人员多用心多勤奋。为了找出低效代码的关键点,代码分析工具将大显身手。

有一个需要坚守的挑战性规则:把JavaScript优化工作推迟到开发的最后阶段。届时,架构转换、对象及其用法的变化、错误修复,所有可变因素都将尘埃落定。开发一套功能完善、容易维护的应用程序是任务清单的核心所在。代码优化过程中分析程序的运用同样也在严肃的应用程序开发中占有一席之地,但不到代码几乎不需改动的最后一刻,不应该轻易实施代码分析。

虽然Venkman的分析程序提供了不少有用功能,例如包含或排除整个文件或其中定义的部分函数,但本节将以讨论Firebug的分析程序为主。原因是大多数Ajax开发人员都会为检查XMLHttpRequest而安装Firebug。尽管Firebug的界面、输出和针对扩展的调用与Venkman有所不同,但其中的原理都是相同的,正像与其他代码分析程序一样。

下面我们将要介绍的Firebug的输出包含许多方面的信息,而且通过单击列标题可以按照相应列的信息重新排序。从左到右,分别描述如下。

l Function——这一列中不仅显示了函数的名称,同时还包括一个指向函数在JavaScript文件中声明位置的链接。通过单击该链接可以迅速看到要分析的代码,从而为研究长时间运行的函数或方法提供了便利。

l Calls——显示了调用该函数的次数。

l Percent——执行该函数所用时间占总执行时间(以毫秒单位显示在分析首部)的百分比,表示函数自有时间(Own Time)。

l Own Time——花在函数直接作用域上的时间。在查找哪个函数占用时间最多时,这里往往能够提供最有用的信息。例如,可以看到运行时间位居第二的urlEncodeObject函数,调用它的时间占用了脚本运行时间的近20%。

l Time——花在该函数作用域中的累计总时间,能够反映出在调用栈中花在这个函数上的总时间。如图4-13所示,run函数需要68.363 ms才能返回,其中包括在它内部调用的所有函数。由于onclick事件首先调用run函数,因此onclick调用的总时间就等于run函数的总时间加上调用run的时间,即68.41 ms

l Avg——花在该函数上的平均总时间。连同最小和最大运行时间一起,这个平均值有助于分析在示例中被多次调用的函数。

l Min——花在该函数上的最小总时间。

l Max——花在该函数上的最大总时间。这个指标通常能够反映出一个函数的伸缩性,因为即使一个函数的平均执行时间很少,但在另外一些情况下其平均时间可能会提高。

l File——与Function类相似,这一列不仅显示了文件名和函数定义所在的行号,同样也提供了到文件中相应行号的链接。利用这种链接功能可以方便地在分析结果与代码的Script选项标签之间切换。

4-13 Firebug中JavaScript分析工具的输出

识别瓶颈

由于前面例子中运行时间最长的函数被库函数和其他对象调用,因此在执行过程中,这个函数成为瓶颈的可能性就比较大。相对而言,执行时间位居第二的函数urlEncodeObject则很少调用其他函数,而且分析结果显示其Own Time事实上完全包含了其Time:

    // 从对象到url编码值的非递归串行化

AjaxRequest.prototype.urlEncodeObject = function(obj) {

    var first = true;

    var string = '';

    for (i in obj) {

        var temp_obj = obj[i];

        // 对字符串直接量不需要使用toString()

        if (typeof temp_obj != 'string') {

            temp_obj = temp_obj.toString();

        }

        var temp_key = encodeURIComponent(i);

        temp_obj = encodeURIComponent(temp_obj);

        if (first) {

            first = false;

            string += temp_key + '=' + temp_obj;

        } else {

            string += '&' + temp_key + '=' + temp_obj;

        }

    }

    return string;

    }

由于这个函数没有调用任何实例变量或方法,因此通过在Firebug的控制台中使用console.profile()console.profileEnd()函数直接调用它,可以发现它的执行速度最快。在前面介绍代码分析的例子中,调用这个函数时只传递了一个小对象:{ "one" : 1 , "two" : 2 },当时只是为了示范它如何编码对象。但为了查找该函数中可能隐含的性能损失,需要让它处理更大些的数据:

    var test = {};

    for (var i = 0; i < 100000; i++) test['i' + i] = i;

上面的调用生成了一个包含10万个成员变量的对象。由于输出会严格匹配输入,因此对键和值的实际编码结果应该会保持最小化,最终是把对象转换成URL编码形式的变量/值对。接下来的调用会启动一个以“Encoding”为标签的分析程序,然后调用编码函数进行编码,最后停止分析程序:

    console.profile("Encoding");

AjaxRequest.prototype.urlEncodeObject(test);

    console.profileEnd("Encoding");

当前函数完成对整个对象的编码花了2287 ms,同时也给了我们进行代码分析的一个良好起点。反观这个函数,其实对它执行时间影响最大的就是循环,因为它需要循环10万次。虽然字符串连接操作也要花点时间,但可以忽略不计,因此该操作没有提升性能的空间。

不过,在连接字符串之前,还需要先声明变量,然后再对对象的值进行比较,最后才会开始编码。虽然编码操作会发生在每个键/值对上,但循环的其他部分肯定会有提升性能的空间。要记住,循环中的每条语句都要运行10万次,而临时的变量不需要在每次迭代时都重新声明。也就是说,只要声明一次就够了,剩下的就是在每次迭代中为临时变量重新赋值。不过,它们仍然需要存在,因为函数不能(或不应该)修改obj变量引用的对象。

接着,来看一看if语句,由于在Firebug控制台中通过循环创建的每个值,它们的类型都是"number"而非"string";这意味着每次都会调用toString()函数。实际上,当作为参数传递到encodeURIComponent()函数中时,不仅对象、函数和数组(对它们进行typeof检查都将返回"object")会被强制转型为字符串,而且数值、布尔值和未定义值也需要进行不同的处理,或者不加处理。

下面我们重写这个函数,不让它处理数值,因为数值在编码时可以直接使用。另外,将布尔值转换为1或0,而不是字符串形式的“true”和“false”;将未定义值简单地表示为空值。遗憾的是,URL编码的值无法表示null值,因此只能将未定义值显示为等价的空字符串:

    // 从对象到url编码值的非递归串行化

AjaxRequest.prototype.urlEncodeObject = function(obj) {

    var first = true;

    var string = '';

    var temp_key;

    var temp_obj;

    for (i in obj) {

        var temp_obj = obj[i];

        temp_key = encodeURIComponent(i);

        switch (typeof temp_obj) {

            case 'number':

                temp_obj = obj[i];

                break;

            case 'boolean':

                temp_obj = (obj[i]) ? 1 : 0;

                break;

            case 'undefined':

                temp_obj = '';

                break;

            default:

                temp_obj = encodeURIComponent(temp_obj);

                break;

        }

        if (first) {

            first = false;

            string += temp_key + '=' + temp_obj;

        } else {

            string += '&' + temp_key + '=' + temp_obj;

        }

    }

    return string;

    }

虽然代码的行数增加了,但这个新函数在处理相同数据时只用了927 ms,即只是修改前所花时间的40%。此外,作为一个额外的收获,布尔值和未定义值都不再以字符串形式来描述它们的值了。

4-14所示的例子分析了一个人类玩家与一个JavaScript对手之间进行Othello(奥赛罗)游戏时的情况,该游戏编写于几年前。通过分析可以看出,调用数量重复的机会很少,因为每个玩家采取的操作在不同游戏间的差异很大。在这种情况下,每个函数的平均、最小和最大运行时间都将变得比调用次数,甚至比整个运行时间的百分比更有价值。

4-14 对一个完整游戏中的JavaScript调用进行分析的结果

由于JavaScript只在游戏玩家采取操作时运行,也因为应用程序遵循了事件驱动的设计,整个运行时间大约394 ms其实是有意义的。不过,其中有两个特殊的函数:movethink,它们的平均时间比其他函数高得多。此外,虽然checkline函数的平均时间较低,但它的最大时间却比预期要多。通过留心与前面同样的问题(例如重复声明、无效递归和循环,以及盲目的逻辑),也可以将这个例子中每个函数的运行时间减少一部分(如图4-15所示)。

4-15 分析程序反映了性能的改善

 

本文来自:http://ajava.org/readbook/AJAX/srajax/16800.html

分享到:
评论

相关推荐

    javascript分析

    这篇博文链接指向的是一个关于JavaScript分析的文章,虽然具体的细节未在描述中给出,但我们可以根据标签“源码”和“工具”来推测文章可能涉及的内容。 源码分析通常指的是对JavaScript代码进行深入研究,理解其...

    发布一个高效的JavaScript分析、压缩工具 JavaScript Analyser

    JavaScript分析、压缩工具 JavaScript Analyser JavaScript Analyser是一款高效的JavaScript分析、压缩工具,旨在提供一款安全、可靠的压缩工具,帮助开发者优化JavaScript代码、提高网站性能。该工具支持语法压缩...

    anatomia:智能JavaScript分析器

    "Anatomia: 智能JavaScript分析器"是针对JavaScript代码进行深度分析和理解的工具,旨在帮助开发者更好地优化、调试和理解他们的代码。 在JavaScript编程中,Anatomia分析器可能涉及以下几个关键知识点: 1. **...

    jsir:JSIR——JavaScript 分析的中间表示

    它的设计初衷是为了在不同的JavaScript分析工具之间建立一个通用的语言模型,以便于分析思路的共享与整合,促进分析技术的进步。JSIR旨在解决一个问题:由于每种分析工具都有自己的内部表示,这使得在工具间转移和...

    JSA:Javascript安全分析(JSA)是用于在Web应用程序安全评估期间进行JavaScript分析的程序

    Javascript安全分析(JSA)是用于在Web应用程序安全评估期间进行JavaScript分析的程序。 jsa.py的功能: 在第一层,第二层和第三层js文件中查找js文件。 例如,http(s)://host.com/file.js包含字符串“ ”,该...

    js-profiler:JavaScript分析工具,库和基准测试集合

    JavaScript分析工具以及分析模块和基准测试库。 JS-Profiler允许您比较有关执行速度和内存消耗的不同技术,运算符和函数。 它以文本或JSON格式报告结果。 JS-Profiler为供电。 目录 命令行界面 图书馆 个人资料 ...

    JavaScript引擎在动态网页采集技术中的应用.pdf

    JavaScript引擎是指能够分析和执行JavaScript语言程序的虚拟机器,也可以称之为JavaScript分析器。开放源码的JavaScript引擎SpiderMonkey给我们提供了一个最基本的并且易于扩展的JavaScript分析器。 JavaScript引擎...

    Sublime-Flow:SublimeText 2 和 3 的 Flow JavaScript 分析器插件

    Flow 的 Sublime 包,静态 JavaScript 分析器。 从 SublimeText 在 JavaScript 项目上运行 支持 Linux 和 OS X。 先决条件 必须安装在您的系统上。 建议将flow安装到/usr/local/bin/ 。 要允许 Flow 在您的项目...

    使用JavaScript编写的语法分析器

    JavaScript语法分析器是一种用于解析JavaScript源代码的工具,它能够将源代码分解成一系列符合语法规则的结构,这些结构通常被称为语法树或抽象语法树(AST)。在本项目中,这个语法分析器是基于LL(1)文法构建的,...

    JavaScript分析、压缩工具JavaScript Analyser

    JavaScript Analyser是一款针对JavaScript代码的分析和压缩工具,旨在提高代码的运行效率并减小文件体积,从而优化网页加载速度。这款工具包含了两种主要的压缩方式:语法压缩和文本压缩。 1. **语法压缩**: 语法...

    基于ArcGIS for javascript的网络分析功能核心代码

    本篇文章将深入探讨基于ArcGIS for JavaScript的网络分析功能的核心代码,以及如何利用这些功能进行高效的空间分析。 网络分析是GIS中的一个重要分支,它主要处理涉及路径选择、服务区域划分、设施定位等问题。在...

    javascript词法分析器

    JavaScript词法分析器是编程语言解析过程中的一个重要环节,它主要负责将源代码转换成一系列有意义的符号,为后续的语法分析和编译或解释提供基础。在这个过程中,词法分析器(也称为扫描器)会识别出源代码中的...

    tern:一个JavaScript代码分析器,可提供深入的跨编辑器语言支持

    Tern是一个独立于编辑器的独立JavaScript分析器,可用于改善现有编辑器JavaScript集成。 得益于一群慷慨的,Tern是MIT许可下的开源软件。 当前有适用于 (和Emacs), , , , , , 和插件,并在 , , , 和 。 ...

    ArcGIS API for JavaScript 4.14 进阶之空间分析(附源码)

    ArcGIS API for JavaScript 4.14 空间分析(本示例展示了空间分析的包含关系,控制缓冲区内点位的显隐)

    sa-sdk-javascript, 传感器分析 JavaScript SDK.zip

    sa-sdk-javascript, 传感器分析 JavaScript SDK sa-sdk-javascript传感器分析 JavaScript SDK紧急招聘前端工程师,运维工程师,大数据工程师等,各种级别的都需要,求发送到我邮箱( shengyonggen@sensorsdata.cn

    JavaScript缓存区分析

    JavaScript缓存区分析是Web开发中的一个重要概念,尤其是在性能优化和大数据处理方面。在这个话题中,我们将深入探讨JavaScript如何管理内存,以及如何利用缓存机制提高应用程序的运行效率。 首先,我们要理解...

    JavaScript代码分析技术综述.pdf

    JavaScript代码分析技术综述 JavaScript代码分析技术综述是指对JavaScript代码进行静态或动态分析,以了解和维护Web系统的前端和后端代码,提高代码质量。JavaScript代码分析技术综述对Web系统的开发和展示产生了...

    期末大作业基于JavaScript的疫情数据可视化分析系统项目源码.zip

    期末大作业JavaScript疫情数据可视化分析系统项目源码,代码注释,新手也看的懂。 期末大作业疫情数据可视化分析系统项目源码,代码注释,新手也看的懂。期末大作业疫情数据可视化分析系统项目源码,代码注释,新手...

    Iroh是JavaScript的动态代码分析工具

    标题中的"Iroh是JavaScript的动态代码分析工具"表明Iroh是一个专门用于帮助开发者在运行时理解和优化JavaScript代码的工具。动态代码分析意味着它可以在程序执行过程中收集数据,而不仅仅是静态地分析源代码。这种...

Global site tag (gtag.js) - Google Analytics