我试图用“随机”数据填充一堆记录,所有这些都是为了测试具有大量数据的应用程序可用性。
所以我虽然 - 完美!,我有我的插入方法,它会做一些“重复检查”,等等。我所要做的就是循环它 x 次。 并使用数据库中的随机值进行填充。
所以我为每组数据访问数据库一次(在我的示例中,用户、thing1 和 thing2 中的三件事)我执行循环,并设置我想随机插入的值 - 并调用我的插入...
它工作正常,直到第 80 个循环左右然后它开始变慢,直到大约 180 个,CPU 风扇全开,CF 耗尽......我试过 在每个循环的末尾添加一个“ sleep ”命令,为“任何”提供解决问题的机会,执行垃圾收集或其他任何操作。
这是日志中的错误 - “java.lang.OutOfMemoryError:超出 GC 开销限制”
运气不是很好。任何人都可以给我一些见解 - 大约 18 个月前我有一个相同的问题,进行一些牌手分析。我认为这仅仅是因为“手牌”的迭代范围太广,我接受了。
但这基本上是 1000 条插入语句,在每条语句之前调用并检查现有记录……这不应该是一个巨大的消耗。??应该是? - 难道不应该在每个循环中清除每个数据结构吗?并在完成后释放每个数据库连接?
我怀疑“答案”比“代码”更正更具理论性和基础性。但我真的很想知道,因为它只会让 future 的代码更加健壮。
谢谢
这是基本的循环结构。
// 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
最佳答案
您在循环内做了太多工作。我会使用这种方法。
在你开始一个循环之前,在你的数据库中创建一个临时表。它必须是暂时的,因为您必须承认同时 Activity 的可能性。
在您的循环中,只需创建您的值并将它们插入到您的临时表中。虽然不理想,但使用 ColdFusion 插入 1000 条记录并不是世界末日。我成功地做得更糟。
一旦循环结束,使用sql来处理你需要处理的重复记录和其他数据问题。然后从临时表写入您的真实数据库表。
关于java - CF "for"循环占用内存/cpu,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32062688/