【问题标题】:How can I avoid using memory when generating thumbnails in ColdFusion 8?在 ColdFusion 8 中生成缩略图时如何避免使用内存?
【发布时间】:2013-06-11 15:55:00
【问题描述】:

我有以下函数用于循环浏览 PDF 文件的目录,并为每个文件创建一个缩略图:

<cffunction name="createThumbnails" returntype="Void" output="false">
    <cfscript>
        //  CONSTANTs
        var _PDF_PATH = APPLICATION.PDFSource & "\PDFs";

        //  Set defaults for private variables
        var _qPDFDir = QueryNew("");
        var _documentId = 0;
        var _sourceFilePath = "";
        var _sku = "";
        var _tempImageFilePath = "";
    </cfscript>

    <!--- Retrieve a list of file names in the directory of unprocessed PDF files --->
    <cfdirectory
        action="list"
        directory="#_PDF_PATH#"
        name="_qPDFDir"
        filter="*.pdf"
        type="file"
        sort="datelastmodified DESC"
        listinfo="name" />

    <!--- Loop through the list of file names in the directory of unprocessed non-PDF files --->
    <cfloop query="_qPDFDir" endrow="500">
        <cfset _sourceFilePath = _PDF_PATH & "\" & name />

        <cfif FileExists(_sourceFilePath) AND IsPDFFile(_sourceFilePath)>
            <cftry>
                <cfpdf
                    action="thumbnail"
                    source="#_sourceFilePath#"
                    destination="#APPLICATION.TempDir#"
                    format="png"
                    scale="100"
                    resolution="high"
                    overwrite="true"
                    pages="1" />

                <cfcatch>
                    <cfscript>
                        FileMove(
                            _sourceFilePath,
                            _PDF_PATH & "\NonFunctioning\"
                            );
                    </cfscript>
               </cfcatch>
            </cftry>

            <cfscript>
                _documentId =
                    REQUEST.UDFLib.File.getFileNameWithoutExtension(name);
                _tempImageFilePath =
                        APPLICATION.TempDir
                    &   "\"
                    &   _documentId
                    &   "_page_1.png";

                if  (FileExists(_tempImageFilePath)) {
                    _sku = getSkuFromDocumentId(_documentId);

                    if  (Len(_sku)) {
                        CreateObject(
                            "component",
                            "cfc.products.Product"
                            ).setClientId(
                                getClientId()
                                ).setId(
                                    _sku
                                    ).createThumbnails(
                                        sourcePath = _tempImageFilePath,
                                        deleteSourceFile = true
                                        );

                        FileMove(
                            _sourceFilePath,
                            APPLICATION.ProcessedPDFDir
                            );
                    }
                }
            </cfscript>
        </cfif>
    </cfloop>

    <cfreturn />
</cffunction>

有些代码不是我想做的——即将文件移动到“NonFunctioning”目录,但这是业务规则所要求的。

我想弄清楚的是,当这个函数运行时如何避免耗尽内存?

使用endrow="500",它在处理了大约 148 个文件后出现java.lang.OutOfMemoryError: GC overhead limit exceeded 错误。

当我在任务管理器(Windows)中查看 jrun.exe 进程时,我可以看到内存越来越大。

有什么办法可以提高这个函数的性能,防止内存被吃掉吗?

【问题讨论】:

  • 看起来你的虚拟机在收集内存上花费了太多时间:stackoverflow.com/questions/4371505/gc-overhead-limit-exceeded。 “超出 GC 开销限制”消息告诉您执行完整 GC 的时间太长,不一定完全耗尽内存。您是否在 CF 实例上配置了 GC 日志记录?我将其设置为每秒运行并检查日志。使用 GCViewer 可视化日志:github.com/chewiebug/GCViewer
  • 这个函数是用这一行调用自己的吗? ).createThumbnails( 如果是这样,你可能有一个无限循环。
  • 您能不能在函数之外执行cfdirectory 并将目录/文件名传递给它。然后在您的主脚本中,让您的 cfdirectory 一次运行 50 个文件,然后通过 cflocation 或 javascript 刷新重定向回自身,直到完成处理文件夹中的所有内容。完成后,您似乎将 PDF 移动到已处理的文件夹中?因此,如果您在一个文件夹中有 500 个文件,一次运行 50 个,则应该执行 10 次。当您的 cfdirectory 停止返回结果时添加 cfabort。
  • @DanBracuk 不,它正在调用不同对象中的函数。
  • @barnyr 谢谢。很好的主意。我会调查的。

标签: memory-leaks coldfusion garbage-collection out-of-memory coldfusion-8


【解决方案1】:

您在循环中创建对象,每次创建对象时 CF 都会保留内存,直到您的页面运行完毕,然后释放内存。

  1. 在循环之外实例化您的对象,并将其保存在一个变量中 并在循环内重新使用对象。
  2. 不要一次处理所有文件(如 steve 建议的那样)处理块,然后创建一个新请求(例如 cfhttp)并再次调用您的处理页面,这将释放第一次处理中使用的任何内存。

【讨论】:

    猜你喜欢
    • 2013-06-28
    • 1970-01-01
    • 1970-01-01
    • 2014-08-27
    • 1970-01-01
    • 2013-06-16
    • 1970-01-01
    • 2013-08-14
    • 1970-01-01
    相关资源
    最近更新 更多