简体   繁体   中英

What's the performance difference between runtime property and real properties?

Does it really matter performance-wise if I write a category with some dynamic properties instead of say subclassing?

(let's keep focus and stick to performance and not design patterns for this post)

Yes, it seems like there's a performance difference. I wouldn't say that it is by a lot. These results is from an iPad 3.

Spent 0.00033 seconds on writing ivar
Spent 0.00010 seconds on reading ivar
Spent 0.00279 seconds on writing ordinary
Spent 0.00200 seconds on reading ordinary
Spent 0.00835 seconds on writing runtime
Spent 0.00763 seconds on reading runtime

When running this

Test *test = [Test new];
int iterations = 10000;

logTimeSpentExecutingBlock(^{
    for(int i = 0; i < iterations; i++) {
        test->ivar = @"foo";
    }
}, @"writing ivar");

logTimeSpentExecutingBlock(^{
    for(int i = 0; i < iterations; i++) {
        test->ivar;
    }
}, @"reading ivar");

logTimeSpentExecutingBlock(^{
    for(int i = 0; i < iterations; i++) {
        test.ordinary = @"foo";
    }
}, @"writing ordinary");

logTimeSpentExecutingBlock(^{
    for(int i = 0; i < iterations; i++) {
        [test ordinary];
    }
}, @"reading ordinary");

logTimeSpentExecutingBlock(^{
    for(int i = 0; i < iterations; i++) {
        test.runtime = @"foo";
    }
}, @"writing runtime");

logTimeSpentExecutingBlock(^{
    for(int i = 0; i < iterations; i++) {
        [test runtime];
    }
}, @"reading runtime");

With this code

void logTimeSpentExecutingBlock(dispatch_block_t block, NSString *label) {
    NSTimeInterval then = CFAbsoluteTimeGetCurrent();
    block();
    NSTimeInterval now = CFAbsoluteTimeGetCurrent();
    NSLog(@"Spent %.5f seconds on %@", now - then, label);
}

@interface Test : NSObject {
@public
    NSString *ivar;
}
@property (nonatomic, strong) NSString *ordinary;
@end

@interface Test (Runtime)
@property (nonatomic, strong) NSString *runtime;
@end

@implementation Test

- (void)setOrdinary:(NSString *)ordinary
{
    // the default implementation checks if the ivar is already equal
    _ordinary = ordinary;
}

@end

@implementation Test (Runtime)

- (NSString *)runtime {
    return objc_getAssociatedObject(self, @selector(runtime));
}

- (void)setRuntime:(NSString *)string {
    objc_setAssociatedObject(self, @selector(runtime), string, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM