调用组件函数与内联代码时的开销 - ColdFusion

Gar*_*ton 9 coldfusion performance components jvm overhead

我一直在诊断生成包含大约50,000行的CSV的性能问题,并且我将其缩小为每行使用一次的单个函数.

经过大量的讨论之后,我发现使用该函数会产生开销,而不是直接将逻辑放在循环中 - 我的问题是:为什么?!

有问题的函数非常简单,它接受一个字符串参数并将其传递给包含大约15个选项的switch/case块 - 返回结果字符串.我已经把一堆定时器放到了这个地方,发现这个函数调用需要花费很多时间(不是全部)才能运行0到200毫秒......但是如果我把完全相同的代码内联,它就坐每次迭代时为0.

所有这些都指向了我对对象实例化的理解中的一个基本问题,我很欣赏一些澄清.

我一直认为,如果我在页面顶部实例化一个组件,或者实际上如果我在一个持久范围内实例化它,如应用程序或会话,那么它将被放入内存并随后调用该组件中的函数将快闪电 然而,似乎调用这些函数有一个开销,而我们只谈了几毫秒,当你必须这样做50,000次时,它会很快加起来.

此外,似乎这样做会消耗资源.我对JVM使用内存的方式并不是特别精通,我已经阅读了它并使用了设置等等,但这是一个压倒性的主题 - 特别是对于那些没有Java开发经验的人.似乎在通过内联代码调用方法时,有时ColdFusion服务只会崩溃而请求永远不会结束.其他时候它确实完成了,虽然方式太慢了.这表明只有当服务器具有处理它的资源时才能完成请求 - 因此方法调用本身正在消耗内存......(?)

如果确实调用方法有附加费用,那么我就有一个大问题.将所有这些代码内联移动并不是真的可行(虽然有问题的函数很简单,但我还需要使用其他许多函数)并且这样做违背了我认为的开发人员的一切!

所以,任何帮助将不胜感激.

为了清楚起见,因为我确信有人会要求它,这里是有问题的代码:

编辑:正如所建议的,我已经将代码更改为使用结构查找而不是CFSwitch - 下面是修改后的代码供参考,但是底部的pastebin链接中还有一个测试应用程序.

在init方法中:

    <cfset  Variables.VehicleCategories = {
            'T1'    : 'Beetle'
        ,   'T1C'   : 'Beetle Cabrio'
        ,   'T2'    : 'Type 2 Split'
        ,   'T2B'   : 'Type 2 Bay'
        ,   'T25'   : 'Type 25'
        ,   'Ghia'  : 'Karmann Ghia'
        ,   'T3'    : 'Type 3'
        ,   'G1'    : 'MK1 Golf'
        ,   'G1C'   : 'MK1 Golf Cabriolet'
        ,   'CADDY' : 'MK1 Caddy'
        ,   'G2'    : 'MK2 Golf'
        ,   'SC1'   : 'MK1/2 Scirocco'
        ,   'T4'    : 'T4'
        ,   'CO'    : 'Corrado'
        ,   'MISC'  : 'MISC'
    } />
Run Code Online (Sandbox Code Playgroud)

被调用的函数:

<cffunction name="getCategory" returntype="string" output="false">
    <cfargument name="vehicleID" required="true" type="string" hint="Vehicle type" />

    <cfscript>
        if (structKeyExists(Variables.VehicleCategories, Arguments.VehicleID)) {
            return Variables.VehicleCategories[Arguments.VehicleID];
        }
        else {
            return 'Base SKUs';
        }
    </cfscript>
</cffunction>
Run Code Online (Sandbox Code Playgroud)

根据要求,我创建了一个测试应用程序来复制此问题:

http://pastebin.com/KE2kUwEf - Application.cfc

http://pastebin.com/X8ZjL7D7 - TestCom.cfc(放在webroot外面的'com'文件夹中)

http://pastebin.com/n8hBLrfd - index.cfm

Hen*_*nry 2

在任何语言中,函数调用总是比内联代码慢。这就是为什么 C++ 中有inline关键字,而在 JVM 领域有 JIT 优化器,如果认为有必要,它会为您内联函数。

现在,ColdFusion 是 JVM 之上的另一层。因此,CF 中的函数不是 JVM 中的函数,因此从 JIT 优化器的角度来看,事情不会 1:1 转换。CFML 函数实际上被编译为 Java 类。此外,每次调用时都会创建诸如arguments, (Java 哈希表)之类的范围。local这些需要时间和内存,因此也需要开销。

...如果我在应用程序或会话等持久作用域中实例化它,那么它将被放入内存中,并且对该组件内的函数的后续调用将快如闪电

它肯定比实例化一个新实例要快,但它不会“快如闪电”,特别是当您在紧密循环中调用它时。

总之,内联函数,如果仍然不够快,找到代码中最慢的部分并用 Java 编写。