优化慢代码-字典枚举

发布于 2024-11-03 12:56:07 字数 4121 浏览 0 评论 0原文

我有以下代码,可将 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];
}

I have the following code that decodes a JSON string into an array of objects that I can then use in a UITableView.

At first I thought the JSON decoding was the slow part but it appears that it is not as the "Dictionary Done" appears almost immediately.

Any ideas on how to get that code to be a little faster?

-(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];

}

EDIT: Added timestamps

Timestamps of the NSLogs as follows...

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

Sample of the 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"

Formatted sample:

{
   "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"
         }
      }
   ]
}

EDIT 2:

So here is "niceDate" that is causing the slowdown!

-(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];
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

如日中天 2024-11-10 12:56:07

我想到了一些事情:

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 次,所以有两个考虑因素:a) 您正在创建/使用/释放这两个实例 >1K 次,而事实上,您没有两个实例, b) 您应该在循环中使用自动释放池。

您应该将此方法设为类方法(或函数),因为它不依赖于该类实例的状态。您的格式化程序将是类(静态)变量。例如:

@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];
}

这修复了 a) 项,但您确实应该在循环内使用自动释放池,因为您使用的 Cocoa 方法返回自动释放对象。通过为循环的每次迭代使用自动释放池,您可以减少代码的内存占用 - 尽管这也会降低性能。我建议您尝试使用和不使用内部自动释放池。

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

    …

    [pool drain];
}

Some things that come to mind:

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

Do you need to use KVC? What is the structure of your JSON data?

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"]];

You always create an instance of ArchiveFlight and parse the timestamp…

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

…even though you don’t have to do that all the time. Depending on how many repeated flightnos you have, this can make a noticeable difference.

Why not read [flight objectForKey:@"flightno"], compare it to lastFlightno and, if and only if they’re different, create an instance, add it to the array, and release it?


Edit: Try the following KVC-free code:

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
    }
}

Edit: You’re creating and (auto)releasing two instances of NSDateFormatter inside this method. In general this would be okay, but since it is being executed >1K times there are two considerations: a) you’re creating/using/releasing those two instances >1K times when, in fact, you don’t have two, b) you should use an autorelease pool in your loop.

You should make this method a class method (or a function) since it doesn’t depend on the state of an instance of that class. Your formatters would be class (static) variables. For instance:

@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];
}

This fixes item a) but you really should use an autorelease pool inside your loop because the Cocoa methods you’re using return autoreleased objects. By using an autorelease pool for each iteration of your loop, you reduce the memory footprint of your code — although this could decrease performance as well. I suggest you try both with and without an inner autorelease pool.

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

    …

    [pool drain];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文