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

Performance 调用组件函数与内联代码时的开销-ColdFusion,performance,coldfusion,jvm,components,overhead,Performance,Coldfusion,Jvm,Components,Overhead,我一直在诊断一个性能问题,生成一个包含大约50000行的CSV,并将其缩小为一个函数,每行使用一次 在经历了很多混乱之后,我发现在使用函数时会有开销,而不是将逻辑直接放在循环中——我的问题是:为什么 所讨论的函数非常简单,它接受一个字符串参数并将其传递给一个包含大约15个选项的开关/大小写块-返回结果字符串。 我在各处都放了一堆计时器,发现这个函数调用的大部分(不是全部)时间都在0到200毫秒之间运行。。。但是,如果我将完全相同的代码内联,则每次迭代时它都位于0 所有这些都指向了我对对象实例化理

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

在经历了很多混乱之后,我发现在使用函数时会有开销,而不是将逻辑直接放在循环中——我的问题是:为什么

所讨论的函数非常简单,它接受一个字符串参数并将其传递给一个包含大约15个选项的开关/大小写块-返回结果字符串。 我在各处都放了一堆计时器,发现这个函数调用的大部分(不是全部)时间都在0到200毫秒之间运行。。。但是,如果我将完全相同的代码内联,则每次迭代时它都位于0

所有这些都指向了我对对象实例化理解中的一个基本问题,我希望得到一些澄清

我总是觉得,如果我在页面顶部实例化一个组件,或者如果我在一个持久作用域(如应用程序或会话)中实例化它,那么它将被放入内存中,随后对该组件中的函数的调用将是闪电般的快。 然而,调用这些函数似乎有一个开销,虽然我们只讨论了几毫秒,但当你不得不这样做50000次时,它很快就会加起来

此外,这样做似乎会消耗资源。我对JVM使用内存的方式不是特别精通,我已经阅读了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'
    } />
<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>

正在调用的函数:

    <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'
    } />
<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>

if(structKeyExists(Variables.VehicleCategories,Arguments.VehicleID)){
返回变量.VehicleCategories[Arguments.VehicleID];
}
否则{
返回“基本SKU”;
}
根据要求,我创建了一个测试应用程序来复制此问题:

-Application.cfc

-TestCom.cfc(放在webroot外部的“com”文件夹中)


-index.cfm

函数调用总是比任何语言中的内联代码慢。这就是为什么C++中有“代码>内联< /COD>关键字,并且在JVM Land中有JIT优化器,它将在需要时为您内联函数。

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

…如果我在应用程序或 会话,然后将其放入内存中并随后调用 该组件中的功能将是闪电般的快

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


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

这里只是一个旁注,因为Railo使用内部类而不是完全独立的类,如果您以这样一种风格编写,从而拥有许多小函数,那么速度会更快。在我的实验中,两个引擎对基本内联代码的性能相似。如果您需要在负载下提高性能,Adobe ColdFusion可以使用大型god函数。由于JVM无法在编译过程中内联ColdFusion函数,因此您永远无法从编译器智能处理代码中获益

如果您创建了一个使用大量显式getter/setter的应用程序,并且发现流量从小流量增加到大流量,那么这一点尤为重要。所有这些小功能都会让你屈服,而大的“上帝”功能会更少

通过一个基本测试,我们运行了100000次迭代,从最慢到最快:

Adobe ColdFusion(许多小函数)(比Java慢200倍) Railo(许多小功能)(速度慢60倍) ColdFusion/Railo(所有代码内联在一个巨大的函数中)(速度慢10倍)
本机Java类(最快)

不确定发生了什么,但我要做的第一件事是将开关更改为结构查找。哦,确保cfcomponent和cffunction标签上有
output=false
!这将增加开销,可能会降低速度。为什么不在页面上创建一个结构并以这种方式引用它呢?我不认为函数是处理这个问题的最佳方法。而且精确的CF和JVM版本可能是相关的,因此应该提供信息。不要阅读所有最新的评论,但要快速注意:如果你有“Report Exe