Мое приложение во время процесса, который я написал, растет в памяти и, кажется, не выпускает его.
Первое, что я хотел бы упомянуть, состоит в том, что основной план того, что я написал, - это:
- Запросить URL-адрес (выборка данных с использованием NSData -initWithContentsOfURL)
- Анализ NSData в NSArray из NSDictionarys с использованием NSJSONSerialization + JSONObjectWithStream
- Цикл через декодированный NSArray, вставляющий/обновляющий/удаляющий записи в базе данных sqlite с использованием фреймворка FMDB с декодированными данными
Приложение выполняет вышеуказанное, однако оно делает это в цикле в течение неопределенного периода времени, в котором приложение отображает "Загрузка" HUD. Я подумал, что, возможно, стоит упомянуть об этом, хотя я считаю несущественным, сколько раз он выполняет этот процесс, поскольку это не должно влиять на использование памяти, если оно было правильно выпущено. Если я ошибаюсь, пожалуйста, сообщите мне.
Мой код работает отлично, ну, он делает то, что он намеревался сделать. Однако, когда я просматриваю код приложения, память, похоже, продолжает расти. Он действительно падает во всех сегментах, но в целом он продолжает расти (IE не выпускает полностью то, что ранее использовал).
У меня, как было сказано ранее, профилируется приложение с помощью Allocations, Leaks, VM Tracker и используется Trace Highlights.
Основные характеристики трассировки. Показывает, что использование памяти постепенно увеличивается, но отбрасывание некоторой памяти (не для всех) означает, что процесс работает достаточно долго, чтобы память достигла высокого уровня использования и завершилась.
Выделение: Кажется, все в порядке. Распределение имеет шипы, но всегда возвращается к тому, где оно началось. Я взял кучу, и они всегда выпадают, оставляя максимум 500-700 кб за сегмент (осталось около 10 минут).
Отслеживание VM: показывает, что память постоянно растет и не освобождает полную память (как обнаружено в основных моментах трассировки). Похоже, что резидент оказался очень высоким
Утечки: в приложении нет утечек
Вот несколько скриншотов программы Allocations/VM Tracker:
Стоит отметить, что я действительно пытался:
- Добавление авторефератов
- "освобождение силы" путем назначения каждого свойства; таких как NSURL, NSRequests и т.д.; до нуля
Мои вопросы:
- Должен ли я делать что-то особенное, чтобы освободить память?
- Как я могу отладить эту проблему?
- Как лучше узнать, что неправильно из данных, которые дает мне Инструменты?
---- РЕДАКТИРОВАТЬ: ----
Здесь код, который отправляет запрос url для извлечения данных.:
- (void) requestAndParse : (NSString *)url
{
NSURL *theURL;
ASIHTTPRequest *request;
NSData *collectedData;
NSError *error;
@try {
// File cache the NSData
theURL = [[NSURL alloc] initWithString: url];
request = [ASIHTTPRequest requestWithURL: theURL];
[request setDownloadDestinationPath: [[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingString:@"/cachefile.txt"]];
[request startSynchronous];
[request waitUntilFinished];
collectedData = [[NSData alloc] initWithContentsOfFile:[[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingString:@"/cachefile.txt"]];
if ([collectedData length] > 0) {
records = [NSJSONSerialization JSONObjectWithData:collectedData options:NSJSONReadingMutableContainers error:&error];
}
}
@catch (NSException *exception) {
// Failed
NSLog(@"Parse error: %@", error);
}
@finally {
// DB updates with the records here
...
// remove file
[[NSFileManager defaultManager] removeItemAtPath:[[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingString:@"/cachefile.txt"] error:nil];
// release properties used
collectedData = nil;
request = nil;
theURL = nil;
}
}
Этот вышеописанный метод вызывается из цикла while в делете приложения. Цикл while является неопределенной длиной, как уже упоминалось ранее.
--- EDIT 2: ---
Ниже приведен пример, который происходит в инструкции @finally (обновление базы данных SQLite с использованием FMDB). В моем классе много таких методов, по одному для каждой таблицы. Все они следуют одному и тому же шаблону, хотя все они дублируются из первого:
-(BOOL) insertBatchOfRecords:(NSArray *)records {
__block BOOL queueReturned = YES;
@autoreleasepool {
FMDatabaseQueue *dbQueue = [self instantiateDatabaseQueue];
[dbQueue inTransaction:^(FMDatabase *tdb, BOOL *rollback) {
if (![tdb open]) {
NSLog(@"Couldn't open DB inside Transaction");
queueReturned = NO;
*rollback = YES;
return;
}
for (NSDictionary *record in records) {
[tdb executeUpdate:@"INSERT OR REPLACE INTO table (attr1, attr2) VALUES (?,?)", [record valueForKey:@"attr1"], [record valueForKey:@"attr2"]];
if ([tdb hadError]) {
queueReturned = NO;
*rollback = YES;
NSLog(@"Failed to insert records because %@", [tdb lastErrorMessage]);
return;
}
}
}];
[dbQueue close];
dbQueue = nil;
}
return queueReturned;
}
И следует метод -instantiateDatabaseQueue:
-(FMDatabaseQueue *) instantiateDatabaseQueue {
@autoreleasepool {
return [FMDatabaseQueue databaseQueueWithPath: [self.getDocumentsDirectory stringByAppendingPathComponent:@"localdb.db"]];
}
}
Авторефераты могут сделать его грязным, но изначально кода у них не было. Я реализовал их в разных местах, чтобы увидеть, есть ли улучшения (не было).
--- EDIT 3 ---
Я профилировал приложение последние несколько дней и до сих пор не повезло найти ответ. Я отделил часть приложения, о котором идет речь, к отдельному собственному проекту, чтобы убедиться, что это действительно вызывает использование памяти. Это оказалось правильным, так как приложение все еще действует одинаково.
Я сделал дополнительные профилирующие фотографии, и мне все еще сложно определить, что на самом деле неправильно. См. Ниже, что распределения выглядят ОК (VM тоже не выглядит слишком плохо для меня?), И там все еще нет утечек (нет изображения этого, потому что там нет!!)
Однако, когда я профилировал Trace Highlights, использование памяти просто продолжает расти, пока не будет слишком много использования (около 70 + МБ на 3GS), а затем сбой из-за использования большого количества памяти.
Я уменьшил проблему, используя ASIHTTPRequest для захвата NSData (вместо этого хранится файл). См. Пересмотренный код выше. Однако проблема все еще сохраняется, требуется больше времени!
Как первоначально, вопрос:
- Что-то не так со второй частью этого процесса приложения?