Skip to content

Instantly share code, notes, and snippets.

@Catfish-Man
Created November 27, 2020 23:37
Show Gist options
  • Save Catfish-Man/6942af953a9e48f80c2d6a6e6d86522f to your computer and use it in GitHub Desktop.
Save Catfish-Man/6942af953a9e48f80c2d6a6e6d86522f to your computer and use it in GitHub Desktop.
#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