Xpages 当使用@Functions时,SSJS中的性能是否会受到影响?

Xpages 当使用@Functions时,SSJS中的性能是否会受到影响?,xpages,Xpages,如果我想解析SSJS中的文本字段,有两个主要工具。内置JavaScript代码和新转换的@函数。@函数是否比使用纯javascript慢?还是没有真正的区别 viewScope.put("length", tmpStr.length) vs 对我来说,@公式似乎没有使用SSJS代码那么快 您可以轻松地使用以下代码进行测试(多次重新加载页面以获得重要结果): 我认为SSJS中的@formula不如传统的@formula快。原因之一是@formula只是SSJS功能之上的另一层,因此需要执行更多的

如果我想解析SSJS中的文本字段,有两个主要工具。内置JavaScript代码和新转换的@函数。@函数是否比使用纯javascript慢?还是没有真正的区别

viewScope.put("length", tmpStr.length)
vs


对我来说,@公式似乎没有使用SSJS代码那么快

您可以轻松地使用以下代码进行测试(多次重新加载页面以获得重要结果):


我认为SSJS中的@formula不如传统的@formula快。原因之一是@formula只是SSJS功能之上的另一层,因此需要执行更多的代码


但这只是一个猜测

所有SSJ都在运行时解析为AST(抽象语法树)。换句话说,您的代码在执行之前一直是一个字符串,此时解析器会检查该字符串以从语法上识别代码包含的内容:哪些字符表示变量,哪些是运算符、函数等。一旦解析完成,运行时引擎能够运行Java代码,这是JavaScript代码的设计初衷

这就是为什么SSJS总是比直接等效的Java慢的原因:如果您刚开始用Java编写代码,那么在构建项目时它就会编译成字节码,但也许更重要的是,在运行时它不必通过解析字符串来“猜测”要运行的代码。。。它只运行您已经定义的Java代码

另一方面,这个过程并没有将各种@Functions的SSJS实现与“原生”JavaScript区别开来;考虑到@Length(tmpStr)只是tmpStr.Length的一个包装器,我并不惊讶Sven在足够的迭代次数下看到了执行时间上的差异。但是,如果您的目标是优化,那么将所有代码从SSJS块移动到bean方法,您将获得比避开@Functions的便利而使用原生JavaScript更大的改进,因为即使原生JavaScript也必须解析为AST。从这个意义上说,两者之间没有根本区别


更新:本答案开头提到的AST解析有一点需要注意。默认情况下,XPages运行时缓存最多400个唯一的SSJS表达式(您可以通过服务器的xsp.properties文件中的
ibm.jscript.cachesize
属性覆盖此限制)。因此,如果遇到与已缓存的表达式(包括空格)完全匹配的表达式,Domino不必为该表达式构造新的AST;它只是引用缓存中已经存在的树。这是一个MRU(“最近使用的”)缓存,因此遇到同一表达式的频率越高,它就越有可能保留在缓存中。无论是否缓存AST,都必须根据当前上下文对其进行评估,与直接使用Java进行编码(例如,
{})相比,某些JavaScript包装器对象确实有额外的开销
成为一个
objectobjectobject
,它类似于
HashMap
,但具有支持闭包的附加功能,如果不使用闭包,这些功能就会被浪费掉)。但这种AST缓存的主要性能含义是,与大多数开发环境不同,代码复制实际上是一件好事,如果只是反复使用相同的精确表达式,那么除了第一个实例之外,其他所有实例都可以跳过语言解析,直接跳转到调用。

tmpStr.length
是浏览器的本机函数(不是Javascript,而是浏览器内部的代码,并经过编译)


@Length(tmpStr)是一个javascript函数,因此它由浏览器解释。

至于@DBLookup,我做了一些测试,发现它比在SSJS中获取视图、然后执行getDocumentByKey并从找到的NotesDocument中获取字段要慢得多。当我循环四个@DBLookups 100次时,速度至少要慢10倍,而不是100次获取文档,然后获取四个字段


霍华德

我也不感到惊讶。每次使用包装器函数都会降低性能。编码有时更注重可读性而不是性能。对于小代码片段,最好使用更简单的@Formulas,而不是(例如)Java对象或编写专用bean-尤其是当性能影响非常小时,您不会注意到…**免责声明:我很少遇到开发人员认为没有问题的代码(没有注意到性能影响)并导致极端情况和服务器崩溃。标记了Sven的答案,因为代码示例证明了这一点。当然,当蒂姆说话时,不需要任何证据。:-)我可以把这两个都标记为答案。这是一个非常有用的答案,因为获取长度非常简单,可以快速地转换为底层Java字节码,而@DBLookup是一个复杂的操作。
viewScope.put("length:, @Length(tmpStr))
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
    <xp:label id="label1">
        <xp:this.value>
            <![CDATA[#{javascript:
            var start = java.lang.System.currentTimeMillis();
            var testString = "0123456789";
            var dummy;
            for(  var i=0;  i<100000; i++ ){
            dummy = @Length( testString )
            }
            var stop = java.lang.System.currentTimeMillis();
            stop - start + " ms"}]]>
        </xp:this.value>
    </xp:label>
    <xp:br></xp:br>
    <xp:br></xp:br>
    <xp:label id="label2">
        <xp:this.value>
            <![CDATA[#{javascript:
            var start = java.lang.System.currentTimeMillis();
            var testString = "0123456789";
            var dummy;
            for( var i=0;  i<100000; i++ ){
            dummy = testString.length;
            }
            var stop = java.lang.System.currentTimeMillis();
            stop - start + " ms"}]]>
        </xp:this.value>
    </xp:label>
</xp:view>