#import <Foundation/Foundation.h> | |
#import <time.h> | |
#define USE_CF_NONOBJC 1 | |
#if USE_CF_NONOBJC | |
extern CFTypeRef _CFNonObjCRetain(CFTypeRef cf); | |
extern void _CFNonObjCRelease(CFTypeRef cf); | |
#endif | |
extern id objc_retain(id obj); | |
extern void objc_release(id obj); | |
@interface RefCountOverrides : NSObject { | |
_Atomic(int64_t) refcount; | |
} | |
@end | |
@implementation RefCountOverrides | |
- (instancetype) init { | |
if ((self = [super init])) { | |
refcount = 1; | |
} | |
return self; | |
} | |
- (oneway void) release { | |
if (--refcount == 0) { | |
[self dealloc]; | |
} | |
} | |
- (id) retain { | |
++refcount; | |
return self; | |
} | |
@end | |
#define ITERS 20000000 | |
#define NSEC_PER_ITER(time) (((double)time * (double)NSEC_PER_SEC) / (double)ITERS) | |
#define TEST(body, name) do {\ | |
start = [NSDate date];\ | |
for (int i = 0; i < ITERS; i++) {\ | |
body\ | |
}\ | |
elapsed = -[start timeIntervalSinceNow];\ | |
if (baseline == 0) printf("Baseline of %f nanoseconds to -retain+-release an NSObject established\n", NSEC_PER_ITER(elapsed));\ | |
else printf("It was %.2fx as fast (%f nanoseconds) to use %s on %s \n", baseline / elapsed, NSEC_PER_ITER(elapsed), name, names[objIdx]);\ | |
} while (0) | |
int main() { | |
#define OBJECT_COUNT 8 | |
id objects[OBJECT_COUNT]; | |
objects[0] = [NSString stringWithUTF8String:"The quick brown fox jümps over the lazy dog!"]; | |
objects[1] = @"The quick brown fox jümps over the lazy dog!"; | |
objects[2] = (id)NSLocaleMeasurementSystem; | |
objects[3] = [NSString stringWithUTF8String:"The quick brown fox jumps over the lazy dog"]; | |
objects[4] = [[[NSObject alloc] init] autorelease]; | |
objects[5] = @5; | |
objects[6] = [[[RefCountOverrides alloc] init] autorelease]; | |
objects[7] = [NSURL fileURLWithPath:@"/System/Library/Frameworks/"]; | |
for (int objIdx = 0; objIdx < OBJECT_COUNT; objIdx++) { | |
id obj = objects[objIdx]; | |
objc_retain(obj); | |
objc_release(obj); | |
NSLog(@"%@", NSStringFromClass([obj class])); | |
} | |
const char *names[OBJECT_COUNT] = { "CFTypeRefs", "constant NSStrings", "constant NSStrings in the shared cache", "regular NSStrings", "NSObjects", "tagged NSObjects", "NSObjects with custom refcounting", "NSURLs" }; | |
NSDate *start = nil; | |
int objIdx = 0; | |
NSTimeInterval elapsed = 0; | |
NSTimeInterval baseline = 0; | |
TEST([objects[4] retain]; [objects[4] release];, "establish a baseline"); | |
baseline = elapsed; | |
for (int objIdx = 0; objIdx < OBJECT_COUNT; objIdx++) { | |
#if USE_CF_NONOBJC | |
if (objIdx == 0 || objIdx == 1 || objIdx == 2) { | |
TEST(_CFNonObjCRetain((CFTypeRef)objects[0]); _CFNonObjCRelease((CFTypeRef)objects[0]);, "_CFNonObjCRetain + _CFNonObjCRelease"); | |
} | |
#endif | |
TEST([objects[objIdx] retain]; [objects[objIdx] release];, "-retain + -release"); | |
TEST(objc_retain(objects[objIdx]); objc_release(objects[objIdx]);, "objc_retain + objc_release"); | |
TEST(CFRetain((CFTypeRef)objects[objIdx]); CFRelease((CFTypeRef)objects[objIdx]);, "CFRetain + CFRelease"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment