Automatic Reference Counting

2,542 views

Published on

Slides della sessione su Automatic Reference Counting, tenuta da Giuseppe Arici alla WhyMCA 2012.

http://www.whymca.org/intervento/automatic-reference-counting

Published in: Technology
  • Be the first to comment

Automatic Reference Counting

  1. 1. Automatic Reference CountingGiuseppe Arici - @giuseppeariciSuperpartes Innovation CampusMOBILE DEVELOPER CONFERENCE 24 – 25 MAGGIO 2012 1
  2. 2. Giuseppe ARiCi  Apple iOS & Mac OS X Addicted Developer Superpartes Innovation Campus & H-Farm  Group Founder & Cocoa Preacher m # Pragma Mark ― pragmamark.org co pe y ;) ci. sep bo ari giu Fan  A Social & Lazy Connected Node → ot a [ tt | in | fb | * ] / giuseppe.arici ard n Im  Mail Forwarder & Spammer vC giuseppe.arici@gmail.com2
  3. 3. ARC3
  4. 4. Attenzione: è un medicinale, leggere attentamente il foglio illustrativo. Consultare il medico se il disturbo si presenta ripetutamente. I medicinali vanno assunti con cautela, per un breve periodo di tempo, non superando le dosi consigliate e solo per le indicazioni riportate nel foglio illustrativo. In caso di dubbio rivolgersi al medico o al farmacista. Tenere il medicinale fuori dalla portata e dalla vista dei bambini. Da usare solo in età adulta.4
  5. 5. OS X & iOS5
  6. 6. Session Timeline • Da dove nasce ? • Che cos’è ? ARC • Come funziona ? • Quando utilizzarlo ?6
  7. 7. Memory Management 100 UIImage <0x12345678> @”Hello WhyMCA !” NSData <0a1b2c3d4e...> UIVIew Backing Store7
  8. 8. Memory Management 100 UIImage <0x12345678> UIVIew Backing Store8
  9. 9. malloc / free UIImage <0x12345678> UIVIew Backing Store9
  10. 10. Manual Reference Counting UIImage <0x12345678> 1 UIVIew Backing Store 310
  11. 11. Manual Reference Counting UIImage <0x12345678> 1 UIVIew Backing Store 211
  12. 12. Manual Reference Counting 0 UIVIew Backing Store 212
  13. 13. Garbage Collection 10013
  14. 14. Garbage Collection 200 Generation 1 Generation 2 Generation 314
  15. 15. Garbage Collection 30015
  16. 16. Garbage Collection 30016
  17. 17. Garbage Collection 30017
  18. 18. Garbage Collection 300 Heap Compaction18
  19. 19. Garbage Collection 400 High Performance Concurrent Garbage Collector19
  20. 20. Garbage Collection 400 X read barrier20
  21. 21. C GC vs21
  22. 22. Puntatori che giocano a Nascondino22
  23. 23. Apple l’ha fatto comunque !23
  24. 24. Limiti del GC Objective-C24
  25. 25. Limiti del GC Objective-C NSData *data = [obj someData]; const char *bytes = [data bytes]; NSUInteger length = [data length]; for (NSUInteger i = 0; i < length; ++i) { printf(“%x”, bytes[i]); }25
  26. 26. Limiti del GC Objective-C26
  27. 27. Limiti del GC Objective-C27
  28. 28. iPhone GC vs28
  29. 29. iPhone Android vs29
  30. 30. 30
  31. 31. Automatic Reference Counting “Automatic Reference Counting (ARC) in Objective-C makes memory management the job of the compiler. By enabling ARC with the new Apple LLVM compiler, you will never need to type retain or release again, dramatically simplifying the development process, while reducing crashes and memory leaks. The compiler has a complete understanding of your objects, and releases each object the instant it is no longer used, so apps run as fast as ever, with predictable, smooth performance.” (Apple, “iOS 5 for developers” – http://developer.apple.com/technologies/ios5)31
  32. 32. Static Analyzer32
  33. 33. Analysis + Auto-Fix + Goodies33
  34. 34. Requisiti di Sistema • iOS 5 • OS X 10.7 • iOS 4 - no runtime ! • OS X 10.6 (64-bit) - no runtime !34
  35. 35. Requisiti di Runtime • Clang (LLVM compiler) 3.0 or later • Obj-C Runtime: objc4 493.9 or later • For iOS4 or OS X 10.6: libarclite_iphoneos.a or libarclite_macosx.a is linked to make ARC work35
  36. 36. Conversione ad ARC36
  37. 37. Conversione ad ARC37
  38. 38. Conversione ad ARC NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // code here [pool release]; @autoreleasepool { // code here } NSString *s = [(id)CFStringCreateWithX(…) autorelease]; NSString *s = CFBridgingRelease(CFStringCreateWithX(…));38
  39. 39. Conversione Automatica From the command line via the -ccc-arcmt-check and -ccc-arcmt-modify arguments.39
  40. 40. Conversione Automatica40
  41. 41. Nessuno è perfetto ! Eccezioni Toll-Free Bridging Strani Autorelease Pools Singleton Structs { case } Giochetti con i Puntatori Blocks41
  42. 42. Conversione Parziale42
  43. 43. Come Funziona ARC ARC è costituito da due componenti principali: • ARC front end compiler • ARC optimizer.43
  44. 44. ARC front end compiler • Inserisce le release correttamente • ivar (strong): inserisce le release nel dealloc • Nel dealloc chiama il [super dealloc] • Genera errori sui qualificatori inconsistenti44
  45. 45. ARC optimizer • Rimuove le retain e le release superflue • Ottimizza le prestazioni, minimizzando le sequenza multiple di retain e [auto]release45
  46. 46. Come Funziona ARC Foo *obj = [[Foo alloc] init]; [foo bar];46
  47. 47. Come Funziona ARC Foo *obj = [[Foo alloc] init]; [foo bar]; [foo release];47
  48. 48. Come Funziona ARC Foo *obj = [[Foo alloc] init]; [foo bar]; objc_release(foo);48
  49. 49. Come Funziona ARC retain retain release release release retain retain retain retain release release release retain retain release release retain release49
  50. 50. Come Funziona ARC Foo *obj = [self foo]; [foo bar]; [self setFoo: newFoo]; [foo baz];50
  51. 51. Come Funziona ARC Foo *obj = objc_retain([self foo]); [foo bar]; [self setFoo: newFoo]; [foo baz]; objc_release(foo);51
  52. 52. Come Funziona ARC - (Foo *) foo { return _foo; }52
  53. 53. Come Funziona ARC - (Foo *) foo { return [[_foo retain] autorelease]; }53
  54. 54. Come Funziona ARC - (Foo *) foo { return objc_retainAutoreleaseReturnValue(_foo); }54
  55. 55. Come Funziona ARC retain autorelease retain release55
  56. 56. Come Funziona ARC retain autorelease retain release56
  57. 57. Come Funziona ARC objc_retainAutoreleaseReturnValue metodo chiamato Autorelease Pool metodo chiamante objc_retainAutorelease dReturnValue57
  58. 58. Come Funziona ARC retain release58
  59. 59. Riferimenti Ciclici 1 159
  60. 60. Riferimenti Ciclici 0 160
  61. 61. zeroing weak references Riferimento “debole” non sicuro nil X release Riferimento __weak X nil61
  62. 62. Instruments62
  63. 63. Memory Management Rules • You have ownership of any objects you create. • You can take ownership of an object using retain. • When no longer needed, you must relinquish ownership of an object you own. • You must not relinquish ownership of an object you don’t own.63
  64. 64. Memory Management Rules Azione su oggetto Objective-C Metodo Objective-C Create and have ownership of it alloc/new/copy/mutableCopy Take ownership of it retain Relinquish it release Dispose of it dealloc64
  65. 65. Qualificatori di Ownership In ARC le variabili id o di tipo oggetto devono avere uno di questi 4 qualificatori di ownership: • __strong (default) • __weak • __unsafe_unretained • __autoreleasing65
  66. 66. __strong /* ARC */ id obj = [[NSObject alloc] init]; { //id __strong obj = [[NSObject alloc] init]; id __strong obj = [[NSObject alloc] init]; id obj = [[NSObject alloc] init]; } /* non-ARC */ { id obj = [[NSObject alloc] init]; [obj release]; } • Default for ‘id’ and object types !66
  67. 67. __weak { id __strong obj0 = [[NSObject alloc] init]; id __weak obj1 = obj0; } • No ownership of the object • When discarded, the variable is assigned to nil • In OS X, not all classes support weak67
  68. 68. __unsafe_unretained id __unsafe_unretained obj = [[NSObject alloc] init]; warning: assigning retained obj to unsafe_unretained variable; obj will be released after assignment [-Warc-unsafe-retained-assign] • UNSAFE • __weak only for iOS5 / OSX Lion (or later). • You must take care of the variables manually68
  69. 69. __autoreleasing @autoreleasepool { id __strong obj = [NSMutableArray array]; } - (BOOL) performOperationWithError:(NSError **)error; - (BOOL) performOperationWithError:(NSError * __autoreleasing *)error; • Pointer to ‘id’ or object types is qualified with __autoreleasing as default69
  70. 70. Initialization id __strong obj0; id __weak obj1; id __autoreleasing obj2; id __strong obj0 = nil; id __weak obj1 = nil; id __autoreleasing obj2 = nil; Any variables that are qualified with __strong, __weak, and __autoreleasing, are initialized with nil.70
  71. 71. Coding With ARC Rules • Che cosa è vietato fare • Che cosa è obbligatorio fare • Che cosa si può fare, con attenzione !71
  72. 72. Rule 1 1. Forget about using retain, release, retainCount, and autorelease [obj release]; error: ARC forbids explicit message send of release [obj release];72
  73. 73. Rule 2 2. Forget about using NSAllocateObject and NSDeallocateObject NSAllocateObject (Class c, NSUInteger extraBytes, NSZone *zone) error: NSAllocateObject is unavailable: not available in automatic reference counting mode73
  74. 74. Rule 3 3. Follow the naming rule for methods related to object creation • if begins { alloc, new, copy, mutableCopy }, the caller has ownership • if begins { init }: - (id) init ... • instance method • return ‘id’ or types of [super|sub]class • not registered in autoreleasepool: the caller has ownership • special case: “initialize”74
  75. 75. Rule 3 (Positive False) -(NSString*) copyRightString; -(NSString*) copyRightString NS_RETURNS_NON_RETAINED; • NS_RETURNS_NON_RETAINED • NS_RETURNS_RETAINED75
  76. 76. Rule 4 4. Forget about calling super dealloc explicitly - (void) dealloc { free(buffer); [super dealloc]; } error: ARC forbids explicit message send of dealloc [super dealloc]; not available in automatic reference counting mode76
  77. 77. Rule 5 5. Use @autoreleasepool Instead of NSAutoreleasePool NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; ... [pool drain]; error: NSAutoreleasePool is unavailable: not available in automatic reference counting mode NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; ^77
  78. 78. Rule 6 6. Forget About Using Zone (NSZone) • If __OBJC2__ is defined, the runtime just ignores zones78
  79. 79. Rule 7 7. Object Type Variables Cannot Be Members of struct or union in C struct Data { NSMutableArray *array; }; error: ARC forbids Objective-C objs in structs or unions NSMutableArray *array;79
  80. 80. Rule 8 8. id and void * Have to Be Cast Explicitly id obj = [[NSObject alloc] init]; void *p = obj; error: implicit conversion of a non-Objective-C pointer type void * to id is disallowed with ARC Special kind of casts: • (__bridge cast) • (__bridge_retained cast) • (__bridge_transfer cast)80
  81. 81. Rule 8 (__bridge cast) id obj = [[NSObject alloc] init]; void *p = (__bridge void *)obj; id o = (__bridge id)p;81
  82. 82. Rule 8 (__bridge_retained cast) /* ARC */ id obj = [[NSObject alloc] init]; void *p = (__bridge_retained void *)obj; /* non-ARC */ id obj = [[NSObject alloc] init]; void *p = obj; [(id)p retain];82
  83. 83. Rule 8 (__bridge_transfer cast) /* ARC */ id obj = (__bridge_transfer id)p; /* non-ARC */ id obj = (id)p; [obj retain]; [(id)p release];83
  84. 84. Rule 8 (Toll-Free Bridging) CFTypeRef CFBridgingRetain(id X) { return (__bridge_retained CFTypeRef)X; } id CFBridgingRelease(CFTypeRef X) { return (__bridge_transfer id)X; } • Convert an object between Obj-C and Core Foundation.84
  85. 85. Rule 8 (Toll-Free Bridging) (__bridge cast) passaggio diretto del blocco puntato nessun trasferimento di ownership CFBridgingRetain() trasferimento di ownership da ARC a Core Foundation CFBridgingRelease() trasferimento di ownership da Core Foundation ad ARC85
  86. 86. Rule 9 9. Switch cases must be wrapped in scope with { } switch (someInt) { case 0: { NSLog(@"Case 0"); } break; }86
  87. 87. Rule 10 10.Exceptions use must be exceptional • For performance purpose, ARC code leaks on exceptions • In Obj-C ARC is not exception-safe for normal releases by default • -fobjc-arc-exceptions / -fno-objc-arc-exceptions: enable / disable • In Obj-C++ -fobjc-arc-exceptions is enabled by default87
  88. 88. Rule 11 11.IBOutlet must be declared as weak • Outlets should be defined as declared properties • Outlets should generally be weak • Top-level objects (or, in iOS, a storyboard scene) should be strong Resource Programming Guide88
  89. 89. Rule 12 12.Singletons should be redefined with dispatch_async static MyClass *sharedManager = nil; - (id)retain + (MyClass*)sharedManager { { return self; @synchronized(self) { } if (sharedManager == nil) { - (NSUInteger)retainCount sharedManager = { [[super allocWithZone:NULL] init]; return NSUIntegerMax; //cannot be released } } } - (oneway void)release return sharedManager; { } //do nothing + (id)allocWithZone:(NSZone *)zone } { - (id)autorelease return [[self sharedManager] retain]; { } return self; - (id)copyWithZone:(NSZone *)zone } { return self; } Resource Programming Guide89
  90. 90. Rule 12 (new singleton) + (id)sharedInstance { static dispatch_once_t predicate; dispatch_once(&predicate, ^{ sharedInstance = [[MyClass alloc] init]; }); return sharedInstance; } Single threaded results Multi threaded results ----------------------- ----------------------- @synchronized: 3.3829 seconds @synchronized: 33.5171 seconds dispatch_once: 0.9891 seconds dispatch_once: 1.6648 seconds http://bjhomer.blogspot.it/2011/09/synchronized-vs-dispatchonce.html90
  91. 91. Rule 13 13.Be careful with performSelector #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" [self performSelector:self.mySel]; #pragma clang diagnostic pop91
  92. 92. Constructs With ARC • Property • Array • Block92
  93. 93. Property Property modifier Ownership qualifier assign __unsafe_unretained copy __strong (note: new copied object is assigned) retain __strong strong __strong unsafe_unretained __unsafe_unretained weak __weak93
  94. 94. Property • Same ownership rules as variables • copy: copies the object by using copyWithZone • manually declared ivar has to have the same ownership qualifier as the property94
  95. 95. Property @property (nonatomic, readonly) MyObj* obj; @synthesize obj; error: ARC forbids synthesizing a property of an Objective-C object with unspecified ownership or storage attribute • ARC forbids synthesizing a readonly property without specifying an ownership qualifier95
  96. 96. Array id objs0[10]; id __weak objs1[20]; NSMutableArray *objs2 = [NSMutableArray alloc] init]; • C static arrays qualified with {__strong, __weak, __autoreleasing} are initialized with nil • For dynamic arrays, should be used containers in the Foundation Framework96
  97. 97. Block void (^block)(void) = ^{ [self doSomethingImportant]; }; ivar = block; // ARC inserts [block copy]97
  98. 98. Block return ^{ [self doSomethingGreat]; };98
  99. 99. Block [array addObject: ^{ … }]; - (id)method { return ^{ … }; }99
  100. 100. Block [[[[[[[[[[block copy] copy] copy] copy] copy] copy] copy] copy] copy] copy]100
  101. 101. Block __block variable in MRC: mutable & “debole” in ARC: mutable & strong ! __weak variable101
  102. 102. Block & Riferimenti Ciclici i MyObj { id ivar; void (^block)(void); } ^{ [self something]; [ivar something]; };102
  103. 103. Block & Riferimenti Ciclici __weak MyClass *weakSelf = self; ^{ [weakSelf something]; };103
  104. 104. Block & Riferimenti Ciclici __weak MyClass *weakSelf = self; ^{ if (weakSelf) { [weakSelf->ivar something]; } };104
  105. 105. Block & Riferimenti Ciclici __weak MyClass *weakSelf = self; ^{ if (weakSelf) { nil !? [weakSelf->ivar something]; } };105
  106. 106. Block & Riferimenti Ciclici __weak MyClass *weakSelf = self; ^{ MyClass *localSelf = weakSelf; if (localSelf) { [localSelf->ivar something]; } };106
  107. 107. ARC MACRO // define some LLVM3 macros if the code is compiled with a different compiler (ie LLVMGCC42) #ifndef __has_feature #define __has_feature(x) 0 #endif #ifndef __has_extension #define __has_extension __has_feature // Compatibility with pre-3.0 compilers. #endif #if __has_feature(objc_arc) && __clang_major__ >= 3 #define ARC_ENABLED 1 #endif // __has_feature(objc_arc) Check @ compile-time if ARC is enabled107
  108. 108. Conclusioni • La Garbage collection é una gran bella idea ! • LObjective-C è un gran bel linguaggio ! MA • LObjective-C + La Garbage Collection non sono una gran bella accoppiata !108
  109. 109. Conclusioni ARC non è la Garbage Collection … anche se ci arriva vicino ;)109
  110. 110. Conclusioni • Le zeroing weak references sono indispensabili ! • Utilizziamo __weak per evitare i riferimenti ciclici ! • Utilizziamo __unsafe_unretained se e solo se non possiamo usare __weak ! • Utilizziamo Instruments Leaks per individuare i riferimenti ciclici !110
  111. 111. Conclusioni • ARC sa gestire soltanto gli oggetti Objective-C ! • Utilizziamo sempre __bridge, CFBridgingRetain, CFBridgingRelease per interagire con Core Foundation !111
  112. 112. Conclusioni • ARC è una figata ! • Iniziamo subito ad usarlo ! • Convertiamo il nostro codice ! • Risparmiamo tempo ! • Risparmiamo denaro ! • Viviamo meglio !112
  113. 113. ARC Reference: documentation and articles Clang: Automatic Reference Counting documentation • Apple: Transitioning to ARC Release Notes • Apple: Xcode New Features User Guide: Automatic Reference Counting • Mike Ash: Friday Q&A about Automatic Reference Counting • StackOverflow: How does automatic reference counting work? • StackOverflow: What are the advantages and disadvantages of using ARC? • StackOverflow: What is the difference between ARC and garbage collection? • informIT: Automatic Reference Counting in Objective-C, Part 1 • informIT: Automatic Reference Counting in Objective-C, Part 2 The Details • Mike Ash: Zeroing weak references without ARC • Github: Support for zeroing weak references on iOS 4 / OS X 10.6 • Assembler - A look under ARC’s hood • MKBlog - Migrating your code to Objective-C ARC • Ray Wenderlich - Beginning ARC in iOS 5 Tutorial113
  114. 114. ARC Reference: videos • WWDC 2011 – Session 322 – Introduction to Automatic Reference Counting • WWDC 2011 – Session 322 – Objective-C Advancements in depth • WWDC 2011 – Session 308 – Blocks and Grand Central Dispatch in Practice • NSScreenCasts Episode 9 - Automatic Reference Counting114
  115. 115. ARC Reference: books • Pro Multithreading and Memory Management for iOS and OS X with ARC, Grand Central Dispatch, and Blocks – By Kazuki Sakamoto, Apress • Programming iOS 5: Fundamentals of iPhone, iPad, and iPod touch Development Second Edition – By Matt Neuburg, O’Reilly115
  116. 116. Sorry !? Automatic Reference Counting Specifications116
  117. 117. Questions ? giuseppe.arici@gmail.com117
  118. 118. Thanks ! giuseppearici.com pragmamark.org118

×