Я пытаюсь заполнить кучу записей «случайными» данными, и все это для проверки удобства использования приложений с большим объемом данных.
Так что я, хотя - отлично! У меня есть свои методы для вставки, он выполняет некоторую «проверку дубликатов» и все такое. Все, что мне нужно сделать, это зациклить его x раз. И заполнить случайными значениями из БД.
Итак, я попадаю в БД один раз для каждого набора данных (три вещи в моем примере: пользователи, вещь1 и вещь2). Я делаю цикл и устанавливаю значения, которые хочу вставить случайным образом, и вызываю свою вставку...
Он работает нормально, примерно до 80-го цикла, затем он начинает замедляться, примерно до 180-го, вентиляторы процессора включаются на полную мощность, и CF расходуется ... Я пытался добавить команду «sleep» в конце каждого цикла, чтобы дать «чему бы то ни было» шанс решить, сделать это сборщиком мусора или чем-то еще.
Вот ошибка в журнале - "java.lang.OutOfMemoryError: превышен лимит накладных расходов GC"
Не большая удача. Может ли кто-нибудь дать мне некоторое представление об этом - у меня была идентичная проблема около 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;
}
Все эти методы работают и возвращают то, что я ожидаю, поэтому, если я опечатал свою «аннотацию», пожалуйста, учтите это ... это потребление памяти или процессора, на котором я ищу входные данные.
Обновление 5 CF 11 для Win 7 — Core i7 4 ГБ ОЗУ Максимальный размер выходного буфера 2048 Минимальный размер кучи JVM 512 МБ Максимальный размер кучи JVM 1024 МБ