Оптимизировать медленный код - перечисление словаря - PullRequest
3 голосов
/ 26 апреля 2011

У меня есть следующий код, который декодирует строку JSON в массив объектов, которые я затем могу использовать в UITableView.

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

Есть идеи, как сделать этот код немного быстрее?

-(void)parseJSON:(NSString *)jsonData{

    NSLog(@"Start parsing");
    NSDictionary *deserializedData = [jsonData objectFromJSONString];
    NSLog(@"Dictionary Done");

    NSArray *flights = [deserializedData valueForKeyPath:@"flights.flight"];
    NSMutableArray *localArray = [[NSMutableArray alloc] init ];
    NSString *lastFlightno =@"";

    for (NSDictionary *flight in flights){

        ArchiveFlight *aFlight = [[ArchiveFlight alloc] initWithFlightno:[flight objectForKey:@"flightno"] route:[flight objectForKey:@"route"]];
        aFlight.flightID = [flight objectForKey:@"primary_key"];
        aFlight.timeStamp = [aFlight niceDate:[flight objectForKey:@"timestamp"]];

        if (![lastFlightno isEqualToString:aFlight.flightno]) {
            [localArray addObject:aFlight];
        }

        lastFlightno =aFlight.flightno;
        [aFlight release];
    }
    NSLog(@"End Parsing");
    [self loadupTable:localArray];
    self.flightArray = localArray;
    [localArray release];

}

РЕДАКТИРОВАТЬ: добавлены метки времени

Временные метки NSLogs следующим образом ...

2011-04-26 13:22:36.104 App[1778:707] Finished request
2011-04-26 13:22:36.109 App[1778:707] Start parsing
2011-04-26 13:22:36.128 App[1778:707] Dictionary Done
2011-04-26 13:22:37.713 App[1778:707] End Parsing

Образец JSON ...

{"flights":[{"flight":{"flightno":"RYR54WP","timestamp":"2011-04-26 12:13:04","route":"EGNX-LEAL","primary_key":"836453"}},{"flight":{"flightno":"RYR24LU","timestamp":"2011-04-26 09:14:03","route":"EVRA-EGNX","primary_key":"831318"}},{"flight":{"flightno":"RYR39WH","timestamp":"2011-04-26 05:33:03","route":"EGNX-EVRA","primary_key":"825492"}},{"flight":{"flightno":"RYR7PX","timestamp":"2011-04-25 20:07:03","route":"LELC-EGNX","primary_key":"816703"}},{"flight":{"flightno":"RYR2VB","timestamp":"2011-04-25 16:57:06","route":"EGNX-LELC","primary_key":"810900"}},{"flight":{"flightno":"RYR3JN","timestamp":"2011-04-25 12:36:04","route":"GCTS-EGNX","primary_key":"802631"}},{"flight":{"flightno":"RYR8GV","timestamp":"2011-04-25 06:07:03","route":"EGNX-GCTS","primary_key":"792945"}},{"flight":{"flightno":"RYR82QR","timestamp":"2011-04-24 19:42:04","route":"EPKK-EGNX","primary_key":"783306"}},{"flight":{"flightno":"RYR51PV","timestamp":"2011-04-24 16:31:05","route":"EGNX-EPKK","primary_key":"777835"}},{"flight":{"flightno":"RYR53AQ","timestamp":"2011-04-24 14:09:05","route":"LIME-EGNX","primary_key":"773572"}},{"flight":{"flightno":"RYR1CX","timestamp":"2011-04-24 11:02:05","route":"EGNX-LIME","primary_key":"768285"}},{"flight":{"flightno":"RYR9ZW","timestamp":"2011-04-24 08:21:04","route":"LEGE-EGNX","primary_key":"764624"}},{"flight":{"flightno":"RYR63BC","timestamp":"2011-04-24 05:48:02","route":"EGNX-LEGE","primary_key":"761726"}},{"flight":{"flightno":"RYR7PX","timestamp":"2011-04-23 19:39:03"

Отформатированный образец:

{
   "flights":[
      {
         "flight":{
            "flightno":"RYR54WP",
            "timestamp":"2011-04-26 12:13:04",
            "route":"EGNX-LEAL",
            "primary_key":"836453"
         }
      },
      {
         "flight":{
            "flightno":"RYR24LU",
            "timestamp":"2011-04-26 09:14:03",
            "route":"EVRA-EGNX",
            "primary_key":"831318"
         }
      }
   ]
}

РЕДАКТИРОВАТЬ 2:

Итак, вот "niceDate", который вызывает замедление!

-(NSString *)niceDate:(NSString *)oldDate{
    NSDateFormatter *formatter = [[[NSDateFormatter alloc] init]autorelease];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSDate *sourceDate = [formatter dateFromString:oldDate];
    NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
    [dateFormatter setDateStyle:NSDateFormatterFullStyle];
    [dateFormatter setTimeStyle:NSDateFormatterLongStyle];
    NSString *timeString = [dateFormatter stringFromDate:sourceDate];
    return [NSString stringWithFormat:@"%@",timeString];
}

1 Ответ

3 голосов
/ 26 апреля 2011

Некоторые вещи, которые приходят на ум:

NSArray *flights = [deserializedData valueForKeyPath:@"flights.flight"];

Вам нужно использовать KVC? Какова структура ваших данных JSON?

ArchiveFlight *aFlight = [[ArchiveFlight alloc] initWithFlightno:[flight objectForKey:@"flightno"] route:[flight objectForKey:@"route"]];
aFlight.flightID = [flight objectForKey:@"primary_key"];
aFlight.timeStamp = [aFlight niceDate:[flight objectForKey:@"timestamp"]];

Вы всегда создаете экземпляр ArchiveFlight и анализируете отметку времени…

    if (![lastFlightno isEqualToString:aFlight.flightno]) {
        [localArray addObject:aFlight];
    }

... даже если вам не нужно делать это все время. В зависимости от того, сколько повторений flightnos у вас есть, это может иметь заметное значение.

Почему бы не прочитать [flight objectForKey:@"flightno"], сравнить его с lastFlightno и, если и только если они отличаются, создать экземпляр, добавить его в массив и выпустить его?

<Ч />

Редактировать: Попробуйте следующий код без KVC:

NSArray *flights = [deserializedData objectForKey:@"flights"];
NSMutableArray *localArray = [[NSMutableArray alloc] init ];
NSString *lastFlightno =@"";

for (NSDictionary *flightWrapper in flights) {
    NSDictionary *flight = [flightWrapper objectForKey:@"flight"];
    NSString *flightno = [flight objectForKey:@"flightno"];

    if (! [flightno isEqual:lastFlightno]) {
        // create instance, add it to the array, release the instance
    }
}
<Ч />

Редактировать: Вы создаете и (автоматически) выпускаете два экземпляра NSDateFormatter внутри этого метода. В общем, это было бы хорошо, но поскольку он выполняется> 1K раз, есть два соображения: ) вы должны использовать пул авто-релиза в вашей петле.

Вы должны сделать этот метод методом класса (или функцией), поскольку он не зависит от состояния экземпляра этого класса. Ваши средства форматирования будут переменными класса (статическими). Например:

@implementation ArchiveFlight

static NSDateFormatter *formatter1; // choose better names!
static NSDateFormatter *formatter2;

+ (void)initialize {
    if (self == [ArchiveFlight class]) {
        formatter1 = [[NSDateFormatter alloc] init];
        [formatter1 setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

        formatter2 = [[NSDateFormatter alloc] init];
        [formatter2 setDateStyle:NSDateFormatterFullStyle];
        [formatter2 setTimeStyle:NSDateFormatterLongStyle];
    }
}

+ (NSString *)niceDate:(NSString *)oldDate {
    NSDate *sourceDate = [formatter1 dateFromString:oldDate];
    NSString *timeString = [formatter2 stringFromDate:sourceDate];
    return timeString;
    // why +stringWithFormat:? It’s not necessary!
    // return [NSString stringWithFormat:@"%@",timeString];
}

Это исправляет пункт а), но вы действительно должны использовать пул авто-релиза внутри вашего цикла, потому что методы Какао, которые вы используете, возвращают автоматически выпущенные объекты. Используя пул автоматического выпуска для каждой итерации цикла, вы уменьшаете объем памяти вашего кода - хотя это может также снизить производительность. Я предлагаю вам попробовать как с внутренним пулом авто-релиза, так и без него.

for (NSDictionary *flightWrapper in flights) {
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    …

    [pool drain];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...