Эффективность Выделения памяти NSXMLParser для iPhone

Я недавно играл с кодом для приложения для iPhone для парсинга XML. Придерживаясь Какао, я решил пойти с классом NSXMLParser. Приложение будет ответственно за парсинг 10,000 + "компьютеры", все, что содержит 6 других строк информации. Для моего теста я проверил, что XML вокруг 900k-1MB в размере.

Моя модель данных должна сохранить каждый компьютер в NSDictionary хешированным уникальным идентификатором. Каждый компьютер также представлен NSDictionary с информацией. Таким образом в конце дня, я заканчиваю с NSDictionary, содержащим 10k другой NSDictionaries.

Проблема, с которой я сталкиваюсь, не о просачивающейся памяти или эффективном устройстве хранения данных структуры данных. Когда мой синтаксический анализатор сделан, общая сумма выделенных объектов только повышается приблизительно на 1 МБ. Проблема состоит в том, что, в то время как NSXMLParser работает, мое объектное выделение подпрыгивает целых 13 МБ. Я мог понять 2 (один для объекта, который я создаю и один для необработанного NSData) плюс немного комнаты для работы, но 13 кажется немного высоким. Я не могу, отображая это, NSXMLParser настолько неэффективен. Мысли?

Код...

Код, чтобы начать анализировать...

NSXMLParser *parser = [[NSXMLParser alloc] initWithData: data];
[parser setDelegate:dictParser];
[parser parse];
output = [[dictParser returnDictionary] retain];        
[parser release];
[dictParser release];

И код делегата синтаксического анализатора...

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {

    if(mutableString)
    {
        [mutableString release];
        mutableString = nil;

    }

    mutableString = [[NSMutableString alloc] init];     

}

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { 
    if(self.mutableString)
    {

        [self.mutableString appendString:string];

    }
}

-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {

    if([elementName isEqualToString:@"size"]){
        //The initial key, tells me how many computers
        returnDictionary = [[NSMutableDictionary alloc] initWithCapacity:[mutableString intValue]];
}

    if([elementName isEqualToString:hashBy]){
    //The unique identifier
        if(mutableDictionary){
            [mutableDictionary release];
            mutableDictionary = nil;
    }       

        mutableDictionary = [[NSMutableDictionary alloc] initWithCapacity:6];

        [returnDictionary setObject:[NSDictionary dictionaryWithDictionary:mutableDictionary] forKey:[NSMutableString stringWithString:mutableString]];
}

    if([fields containsObject:elementName]){
        //Any of the elements from a single computer that I am looking for
        [mutableDictionary setObject:mutableString forKey:elementName];
}
}

Все инициализированное и выпущенное правильно. Снова, я не получаю ошибки или утечку. Просто неэффективный.

Спасибо за любые мысли!

6
задан Staros 22 January 2010 в 15:35
поделиться

7 ответов

Не удается сказать что-то конкретное в вашем коде, но посмотрите на образец Apple XMLPERFormance . Это сравнивает производительность NSXMLParser и LibxML - результаты - это определенно в пользу последнего. В одном из моих проектов переключаются с NSXMLParser на LibxML, дали большой повышение производительности, поэтому я предлагаю использовать его.

3
ответ дан 10 December 2019 в 02:47
поделиться

NSXMLParser - это память боров:

  1. Это не настоящий потоковый анализатор: initwithurl : скачат полный XML перед обработкой его. Для памяти использовать это плохо, так как оно должно выделить память для полного XML викать не может быть восстановлено до конец анализа. Для производительности это Также плохо, так как вы не можете переопределить Ио интенсивная часть загрузки и процессорная часть расставания.
  2. Это не выпустит память. Кажется что строки / словари созданы Во время разбора сохраняется вокруг до конца анализа. Я пробовал улучшить его с творческим использованием NSAUTRELEASEPOOL Но без какого-либо успех.

Альтернативы являются libxml и aqxmlparser , который представляет собой совместимую с помощью NSXMLParser вокруг libxml или objectivexml .

См. Мой блог для более подробной информации.

6
ответ дан 10 December 2019 в 02:47
поделиться

Лучшая точность, кажется, 9 метров. Общие ценности (открытый, хороший охват) составляет 17 м, 23 м и 49 метров. С деревьями, покрывающими небо, вы, вероятно, останусь под сто метров, но вряд ли достаточно точны для ГИС или что-то подобное.

-121--3665318-

Я использовал NSXMLParser для разбора файлов XML с примерно 500 записей на 700k или около того. Я обнаружил, что это было в верхнем конце ограничения памяти iPhone 3G. Память расширилась намного больше, чем размер файла XML, по времени достигая 15 МБ. Проблема заключалась в том, что я хранил записи в массиве, поэтому оба были в памяти одновременно. При разборе готовая память снова снизилась, но если она когда-либо достигла 15 или 20 МБ, приложение будет сбой. libxml должен быть гораздо больше памяти эффективен.

Вы также можете попробовать хранить созданные объекты с основными данными, а не в массиве. Основные данные осторожно позаботятся о памяти, более отменившимися объектами, когда они не нужны.

С моим приложением я сократил накладные расходы на память, оптимизируя другие детали, чтобы общая память никогда не достигла верхнего предела.

0
ответ дан 10 December 2019 в 02:47
поделиться

просто включена в libxml .

Бит головной боли, но ссылка Владимир опубликовала была огромная помощь.

Теперь блумок для файла 900K - 1 МБ составляет всего 2-3 МБ. Кроме того, потому что это потоковый парсер, это сделано практически сразу после NSURLREQUEST .

Окончательный ответ - libxml.

Спасибо за всю вашу помощь, ребята!

0
ответ дан 10 December 2019 в 02:47
поделиться

Если вы хотите знать, где находится ваша память, запустите код под инструментами Используя шаблон объекта ALLOC и сортировать список классов по общему размеру. После того, как общий использование памяти становится огромным, вы увидите один класс или несколько классов как крупнейшие оккупанты памяти.

Затем сверните на один из этих классов и изучите экземпляры, чтобы увидеть, что их создало.

Тогда вы знаете , от доказательств, где находится ваша проблема.

0
ответ дан 10 December 2019 в 02:47
поделиться

Если вы ищете замену NSXMLParser, которая может обрабатывать потоковую передачу больших XML-документов по http, вас может заинтересовать мой Expat Objective C Wrapper.

0
ответ дан 10 December 2019 в 02:47
поделиться

Я использовал AQXMLParser раньше, и он определенно намного эффективнее с точки зрения памяти, чем NSXMLParser.

0
ответ дан 10 December 2019 в 02:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: