プロパティのatomicとnonatomic  結論はないよ!

今度はatomictとnonatomic, mutableとimmutable, retainとcopyでどんな違いがあるか調べてみたよ!

テストコード(長いよ!)

#import <Foundation/Foundation.h>

@interface Test01 : NSObject
@property (nonatomic,assign) id obj;
@property (nonatomic, copy) id obj1;
@property (nonatomic, retain) id obj2;
@end
@interface Test02 : NSObject
@property (assign) id obj;
@property (copy) id obj1;
@property (retain) id obj2;
@end

int main( int argc, char *argv[])
{
	id pool = [[NSAutoreleasePool alloc] init];

	if(argc<4) return -1;
	Class aClass = NULL;
	void (^strategy)(Test01 *obj, id val) = NULL;
	id x[2];
	switch(atoi(argv[1])) {
		case 0:
			aClass = [Test01 class];
			printf("\nnonatomic ");
			break;
		case 1:
			aClass = [Test02 class];
			printf("\natomic ");
			break;
	}
	switch(atoi(argv[2])) {
		case 0:
			strategy = ^(Test01 *obj, id val) { obj.obj1 = val;};
			printf("setter copy ");
			break;
		case 1:
			strategy = ^(Test01 *obj, id val) { obj.obj2 = val;};
			printf("setter retain ");
			break;
		case 2:
			strategy = ^(Test01 *obj, id val) { val = obj.obj1;};
			printf("getter copy ");
			break;
		case 3:
			strategy = ^(Test01 *obj, id val) { val = obj.obj2;};
			printf("getter retain ");
			break;
	}
	switch(atoi(argv[3])) {
		case 0:
			x[0] = @"0";
			x[1] = @"1";
			printf("immutable");
			break;
		case 1:
			x[0] = [NSMutableString stringWithString:@"0"];
			x[1] = [NSMutableString stringWithString:@"1"];
			printf("mutable");
			break;
		default:
			return -1;
	}
	if(!aClass) return -1;
	if(!strategy) return -1;

	Test01 *test = [[[aClass alloc] init] autorelease];
	
	for(unsigned long i = 0; i < 100000000; i++) {
		strategy(test, x[i%2]);
	}

	[pool release];
	return 0;
}

@implementation Test01
@synthesize obj, obj1, obj2;
@end

@implementation Test02
@synthesize obj, obj1, obj2;
@end

無駄に長いね。そして、無駄にBlocksだね! 関数ポインタでも全く問題ないね!

実行してみたよ!

MBP:~/tmp/src masaki$ make test
cc   -framework Foundation -framework AppKit  test.m   -o test
MBP:~/tmp/src masaki$ for i in 0 1; do for j in 0 1 2 3; do for k in 0 1 ; do time ./test $i $j $k; done; done; done; 

nonatomic setter copy immutable
real	0m3.215s
user	0m2.994s
sys	0m0.013s

nonatomic setter copy mutable
real	0m8.850s
user	0m8.056s
sys	0m0.026s

nonatomic setter retain immutable
real	0m3.403s
user	0m3.150s
sys	0m0.016s

nonatomic setter retain mutable
real	0m10.158s
user	0m9.164s
sys	0m0.031s

nonatomic getter copy immutable
real	0m1.585s
user	0m1.426s
sys	0m0.008s

nonatomic getter copy mutable
real	0m1.608s
user	0m1.411s
sys	0m0.009s

nonatomic getter retain immutable
real	0m1.290s
user	0m1.144s
sys	0m0.010s

nonatomic getter retain mutable
real	0m1.412s
user	0m1.155s
sys	0m0.011s

atomic setter copy immutable
real	0m6.460s
user	0m5.139s
sys	0m0.031s

atomic setter copy mutable
real	0m12.123s
user	0m10.413s
sys	0m0.047s

atomic setter retain immutable
real	0m5.576s
user	0m5.163s
sys	0m0.018s

atomic setter retain mutable
real	0m11.703s
user	0m10.808s
sys	0m0.033s

atomic getter copy immutable
real	0m4.174s
user	0m3.837s
sys	0m0.015s

atomic getter copy mutable
real	0m4.135s
user	0m3.838s
sys	0m0.016s

atomic getter retain immutable
real	0m4.204s
user	0m3.823s
sys	0m0.018s

atomic getter retain mutable
real	0m4.218s
user	0m3.838s
sys	0m0.016s

なるほどね! さっぱり分かんないね!
ちなみにリテラル(もちろんimmutable)なNSStringのcopyとretainはどちらも何もしないからね!びっくりだね!

出力はawkでいじりやすくしてあるからね!

決して力つきたとかじゃないからね!!!