使用@Function时SSJS是否有性能损失?

时间:2012-03-22 12:11:41

标签: xpages

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

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

VS

viewScope.put("length:, @Length(tmpStr))

5 个答案:

答案 0 :(得分:16)

所有SSJS在运行时被解析为AST(抽象语法树)。换句话说,你的代码只是在它执行的确切时刻之前保持一个字符串,此时解析器检查该字符串以语法识别代码包含的内容:哪些字符表示变量,即运算符,函数等。解析完成后,运行时引擎能够运行Java代码,这是JavaScript代码设计的粗略近似。

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

另一方面,这个过程并没有将各种@Functions的SSJS实现与“本机”JavaScript区分开来。鉴于@Length(tmpStr)只是tmpStr.length的包装器,在给定足够的迭代时Sven看到执行时间的差异并不让我感到惊讶。但是如果您的目标是优化,那么通过将所有代码从SSJS块移动到bean方法,您将获得更多的改进,而不是通过避免使用@Functions来支持原生JavaScript,因为即使是本机JavaScript也必须被解析为AST。从这个意义上讲,两者之间没有根本的区别。

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

答案 1 :(得分:4)

对我而言,似乎@Formula没有使用SSJS代码那么快。

您可以轻松地使用类似这样的代码进行测试(多次重新加载页面以获得严重的结果):

<?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>

答案 2 :(得分:1)

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

但这只是一个疯狂的猜测。

答案 3 :(得分:1)

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

霍华德

答案 4 :(得分:0)

tmpStr.length是浏览器本机函数(不是在Javascript中,而是在浏览器中编写代码)

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