【问题标题】:CF "for" loop eating memory / cpuCF“for”循环吃内存/cpu
【发布时间】:2015-11-10 19:35:17
【问题描述】:

我正在尝试用“随机”数据填充一堆记录,所有这些都是为了使用大量数据测试应用程序的可用性。

所以我虽然 - 完美!,我有我的插入方法,它会做一些“重复检查”,等等。我所要做的就是循环它 x 次。 并使用数据库中的随机值填充。

所以我为每组数据(在我的示例中为三件事,用户、事物 1 和事物 2)打了一次数据库,我执行循环,并设置我想要随机插入的值 - 并调用我的插入...

它工作正常,直到第 80 个循环左右然后它开始变慢,直到大约 180 个,CPU 风扇完全运转,并且 CF 用完了......我试过了 在每个循环结束时添加一个“睡眠”命令,让“任何”有机会解决,做垃圾收集或其他什么。

这是日志中的错误 - “java.lang.OutOfMemoryError : GC overhead limit exceeded”

运气不是很好。谁能给我一些见解 - 大约 18 个月前我有一个相同的问题,东一些牌手分析。我认为这仅仅是因为“牌手”的迭代过于广泛,我接受了这一点。

但这基本上是 1000 个插入语句,在每个语句之前调用并检查现有记录...这不应该是一个巨大的消耗。??应该是? - 不应该在每个循环中清除每个数据结构吗?并在完成后释放每个数据库连接?

我怀疑“答案”比“代码”更正更具理论性和基础性。但我真的很想知道,因为它只会帮助未来的代码更加健壮。

谢谢

这是基本的循环结构。

// get master lists of all available data - will use for random selection
users  = createObject( 'component', 'users' ).getFullList;
thing1 = createObject( 'component', 'thing1' ).getFullList;
thing2 = createObject( 'component', 'thing2' ).getFullList;

for ( i = 1; i <= 1000; i++ ) {
    // get random id from within the recorset returned
    args = structNew();
    args['app_id'] = 1;
    args['user_id']   = users.id[RandRange( 1, users.recordcount , 'SHA1PRNG' )];
    args['thing1_id'] = thing1.id[RandRange( 1, thing1.recordcount , 'SHA1PRNG' )];
    args['thing2_id'] = thing2.id[RandRange( 1, thing2.recordcount , 'SHA1PRNG' )];

    // cehck for dups and put the data
    return = putData( argumentCollection = args );

    // tell me count and let me know if it succeeded
    writeoutput( '( #i# = #return# )' );

    // flush it - so I know where we are
    getPageContext().getOut().flush();

    // help garbage collection? something is causing a bog down
    structClear( args );
}

下面是从循环之前实例化的对象调用的其他方法。 循环中没有创建“过多”组件 - 所有这些都在循环之前发生一次。

/*
    methods from other components
*/

putData( [my arguments] ) {
    var isDuplicate = false;

    transaction action = 'begin' {
        // check for existing (dont allow dups)
        isDuplicate = chekForDuplicate( argumentcollection = arguments );

        if ( !isDuplicate ) {
            // deduct from users balance
            deduct = deductFromBalance(
                                        user_id = arguments.user_id
                                        ,units = 1
                                    );

            if ( deduct.success ) {
                try {
                    // put in users acct
                    insertData( argumentcollection = arguments );
                    transaction action = 'commit';
                    return true;
                } catch ( any e ) {
                    transaction action = 'rollback';
                    return false;
                }
            } else {
                transaction action = 'rollback';
                return false;
            }
        } else {
            transaction action = 'rollback';
            return false;
        }
    }
}

chekForDuplicate( [my arguments] ) {
    // check for uplicate
    var r = new Query(
        datasource = "myDSN"
        ,sql = "
            SELECT
                id
            FROM
                eventTable                  
            WHERE
                app_id = ?
            AND
                user_id = ?
            AND
                thing1_id = ?
            AND
                thing2_id = ?
        "
        ,parameters = [
                 { value = val( arguments.app_id ), cfsqltype = 'CF_SQL_INTEGER' }
                ,{ value = val( arguments.user_id ), cfsqltype = 'CF_SQL_INTEGER' }
                ,{ value = val( arguments.thing1_id ), cfsqltype = 'CF_SQL_INTEGER' }
                ,{ value = val( arguments.thing2_id ), cfsqltype = 'CF_SQL_INTEGER' }
        ]
    ).execute().getPrefix();

    if ( r.recordcount ) {
        return true;
    } else {
        return false;
    }
}


deductFromBalance( [myArgs] ) {
    var r = {};
        r['beginningBalance'] = checkBalance( arguments.user_id );
        r['unit'] = arguments.units;
        r['success'] = false;

        if ( r['beginningBalance'] > 0 ) {
            adjustBalance( argumentCollection = arguments );
        }

        r['endingBalance'] = checkBalance( arguments.user_id );

        if ( r['beginningBalance'] - r['endingBalance'] == r['unit'] ) {
            r['success'] = true;
        }

    return r;
}

checkBalance( [myArgs] ) {
    // return the balance for this user
    var r = new Query(
            datasource = 'myDSN'
            ,sql = "
                SELECT
                    balance
                FROM
                    users
                WHERE
                    id = ?
            "
            ,parameters = [
                { value = val( arguments.user_id ), cfsqltype = 'CF_SQL_INTEGER' }
            ]
        ).execute().getResult();

    return val( r.balance );
}

adjustBalance( [myArgs] ) {
    var r = false;
    var bal = checkBalance( arguments.user_id );

    if ( bal >= 0 && arguments.units > 0 ) {
        var q = new Query(
            datasource = 'myDSN'
            ,sql = "
                UPDATE
                    users
                SET
                    balance = ( balance + ? )
                WHERE
                    id = ?
            "
            ,parameters = [
                 { value = val( arguments.units ), cfsqltype = 'CF_SQL_INTEGER' }
                ,{ value = val( arguments.user_id ), cfsqltype = 'CF_SQL_INTEGER' }
            ]
        ).execute();

        r = true;
    }
    return r;
}

insertData( [myArgs] ) {
    // insert data
    var r = new Query(
            datasource = "myDSN"
            ,sql = "
                INSERT INTO
                    eventTable
                    (
                        app_id
                        ,user_id
                        ,thing1_id
                        ,thing2_id
                    )
                VALUES
                    (
                        ?
                        ,?
                        ,?
                        ,?
                    )
            "
            ,parameters = [
                 { value = val( arguments.app_id ), cfsqltype = 'CF_SQL_INTEGER' }
                ,{ value = val( arguments.user_id ), cfsqltype = 'CF_SQL_INTEGER' }
                ,{ value = val( arguments.thing1_id ), cfsqltype = 'CF_SQL_INTEGER' }
                ,{ value = val( arguments.thing2_id ), cfsqltype = 'CF_SQL_INTEGER' }
            ]
        ).execute().getPrefix();

    return r;
}

所有这些方法都能正常工作并返回我所期望的结果,所以如果我打错了我的“摘要”,请允许...这是我正在搜索输入的内存或 CPU 的消耗。

Win 7 上的 CF 11 更新 5 - Core i7 4gig ram 最大输出缓冲区大小 2048 最小 JVM 堆大小 512 MB 最大 JVM 堆大小 1024 MB

【问题讨论】:

  • 一种调试技术是开始注释掉各个函数调用,重新运行,看看您的问题是否仍然存在。例如,首先注释掉对 putData() 的调用。如果问题仍然存在,请注释掉对 insertData 的调用。冲洗并与其他函数调用重复。
  • 这可能与您的内存问题无关,但您的 deductFromBalance 在 try/catch 中不受保护,因此其中的任何异常都会扰乱您的事务状态。
  • @sam,我已经做到了... insertData() 似乎是问题所在。并感谢尝试/捕获建议
  • 您为 CF 实例分配了多少内存?在请求完全处理之前,AFAIK CF 不会释放 ram。
  • @jpmyob - 可能想看看this thread。它有点过时并且基本情况略有不同(批量插入 - 可以使用其他工具更有效地完成),但有些帖子可能是相关的。

标签: java mysql loops coldfusion coldfusion-11


【解决方案1】:

你在循环中做了太多的工作。我会使用这种方法。

在开始循环之前,请在数据库中创建一个临时表。它必须是暂时的,因为您必须承认同时活动的可能性。

在您的循环中,只需创建您的值并将它们插入到您的临时表中。虽然不理想,但使用 ColdFusion 插入 1000 条记录并不是世界末日。我成功地做得更糟。

循环结束后,使用 sql 来处理重复记录和其他数据问题。然后从临时表写入您的真实数据库表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-30
    • 1970-01-01
    • 2021-10-28
    • 2015-03-21
    • 2019-11-10
    • 2015-11-12
    • 1970-01-01
    相关资源
    最近更新 更多