gpt4 book ai didi

coldfusion - 这个 cfqueryparam 内存泄漏有解决方案吗?

转载 作者:行者123 更新时间:2023-12-03 09:40:35 26 4
gpt4 key购买 nike

更新:

  • 我已将错误提交给 Adob​​e 并引用了这个 SO 问题
  • 在出现问题的实际代码中,我决定只删除我对 cfqueryparam 的使用。我现在使用自定义函数根据类型格式化参数。我将不得不处理安全和速度方面的问题,但它可以让特定进程在当前负载下正常工作。
  • 将来我计划将数据文件拉入数据库中的临时表中。然后我会尽可能使用 SQL 对数据执行操作并将数据传输到事件表中,而不是依赖 ColdFusion


  • 我在插入数据时使用 cfqueryparam 标签循环查询时遇到问题。 (我没有测试过选择或更新查询)。循环逐渐占用更多内存,直到请求完成才会释放这些内存。但是,只有在函数中循环查询时才会出现问题。

    它似乎对使用的 cfqueryparam 标签的数量非常敏感。在这个例子中,有 15 个值被插入,但是在我的代码中实际上需要它来工作,我插入了未知数量的值,这会使问题更加严重。

    下面是显示问题的代码。给它一个数据源名称(在 MSSQL 上测试),它将创建一个 tmp 表并插入记录作为示例,无论是否在函数中。内存使用显示在非函数循环之前,之后,然后是函数内循环之后。它还请求垃圾收集并在输出内存信息之前等待 10 秒,以确保它尽可能准确地显示信息。

    根据我对这个特定测试的经验,函数内循环导致使用了超过 200mb 的内存。在我的现实世界中使用它会导致 ColdFusion 崩溃 :-(
    <cfsetting enablecfoutputonly="true">
    <cfsetting requesttimeout="600">

    <cfset insertCount = 100000>
    <cfset dsn = "TmpDB">

    <cfset dropTmpTable()>
    <cfset createTmpTable()>

    <cfset showMemory("Before")>
    <cfflush interval="1">

    <cfloop from="1" to="#insertCount#" index="i">
    <cfquery name="testq" datasource="#dsn#">
    INSERT INTO tmp ( [col1],[col2],[col3],[col4],[col5],[col6],[col7],[col8],[col9],[col10],[col11],[col12],[col13],[col14],[col15] )
    VALUES ( <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR"> )
    </cfquery>
    </cfloop>

    <cfset showMemory("After Non-Function INSERTS")>
    <cfflush interval="1">

    <cfset funcTest()>

    <cfset showMemory("After Function based INSERTS")>

    <cfset dropTmpTable()>

    <cffunction name="funcTest" output="false">
    <cfset var i = 0>
    <cfset var testq = "">
    <cfloop from="1" to="#insertCount#" index="i">
    <cfquery name="testq" datasource="#dsn#">
    INSERT INTO tmp ( [col1],[col2],[col3],[col4],[col5],[col6],[col7],[col8],[col9],[col10],[col11],[col12],[col13],[col14],[col15] )
    VALUES ( <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR">, <cfqueryparam value="TestValue" cfsqltype="CF_SQL_CHAR"> )
    </cfquery>
    </cfloop>
    </cffunction>

    <cffunction name="showMemory" output="true">
    <cfargument name="label" required="true">

    <cfset var runtime = "">
    <cfset var memoryUsed = "">
    <cfset requestGC("10")>
    <cfset runtime = CreateObject("java","java.lang.Runtime").getRuntime()>
    <cfset memoryUsed = (runtime.totalMemory() - runtime.freeMemory()) / 1024 / 1024>
    <cfoutput>
    <h2>#arguments.label#</h2>
    Memory Used: #Round(memoryUsed)#mb
    </cfoutput>
    </cffunction>

    <cffunction name="requestGC">
    <cfargument name="waitSeconds" required="false" default="0" type="numeric">
    <cfscript>
    createObject("java","java.lang.Runtime").getRuntime().gc();
    createObject("java", "java.lang.Thread").sleep(arguments.waitSeconds*1000);
    </cfscript>
    </cffunction>

    <cffunction name="dropTmpTable" output="false">
    <cftry>
    <cfquery datasource="#dsn#">
    DROP TABLE tmp
    </cfquery>
    <cfcatch type="database"></cfcatch>
    </cftry>
    </cffunction>

    <cffunction name="createTmpTable" output="false">
    <cfquery datasource="#dsn#">
    CREATE TABLE tmp(
    col1 nchar(10) NULL, col2 nchar(10) NULL, col3 nchar(10) NULL, col4 nchar(10) NULL, col5 nchar(10) NULL, col6 nchar(10) NULL, col7 nchar(10) NULL, col8 nchar(10) NULL, col9 nchar(10) NULL, col10 nchar(10) NULL, col11 nchar(10) NULL, col12 nchar(10) NULL, col13 nchar(10) NULL, col14 nchar(10) NULL, col15 nchar(10) NULL
    ) ON [PRIMARY]
    </cfquery>
    </cffunction>

    只是为了表明可以在操作期间释放内存,以下示例代码构建了一个更大的结构,并显示了变量被覆盖和垃圾收集之前和之后使用的内存。在我的运行中,填充后使用的内存为 118mb,覆盖和垃圾收集后为 31mb。
    <cfset showMemory("Before struct creation")>
    <cfflush interval="1">

    <cfset tmpStruct = {}>
    <cfloop from="1" to="1000000" index="i">
    <cfset tmpStruct["index:#i#"] = "testvalue testvalue testvalue testvalue testvalue testvalue testvalue testvalue testvalue testvalue">
    </cfloop>

    <cfset showMemory("After struct population")>
    <cfflush interval="1">

    <cfset tmpStruct = {}>
    <cfset showMemory("After struct overwritten")>

    最佳答案

    你在管理员中调试了吗?

    如果是这样,即使您有 showdebugoutput="false" ,CF 也会保留有关所有这些查询的调试信息,并且有这么多查询,调试信息可能会迅速建立。

    此外,如果您真的有 80,000 行要插入,您可能希望以不同的方式执行此操作 - 例如生成直接针对 DB 运行的导入脚本(没有 CF/JDBC 妨碍)。

    关于coldfusion - 这个 cfqueryparam 内存泄漏有解决方案吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/855066/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com