Friday, December 1, 2017

Garbage Collection vs. Automatic Reference Counting


In the previous blog post, we discussed how iOS uses Automatic Reference Counting (ARC) as its object lifetime management system. In this post I try to point out some of the differences the ARC has compare to a garbage collection or more specifically tracing garbage collection (to be more precise reference counting and tracing are the two different implementation of the garbage collection. In other words ARC is a form of garbage collection. Since tracing garbage collection is the most common type of garbage collection, usually the term "garbage collection" refers to tracing garbage collection).   

Garbage Collection

Garbage Collection (GC) is a form of automatic memory management attempts to reclaim garbage, or memory occupied by objects that are no longer in use by the program. Prior to existence of any garbage collection you had to manually add calls to retain and release (in other languages "free" or "destroy")
There are several strategies to implement a garbage collection, the most common two are tracing, and reference counting. Tracing garbage collection is used by the .NET and Java platforms.

Garbage collection acts at run-time. It detects unused objects and it releases them once no part of your code is using them anymore. This happens at indeterminate intervals (either after a certain amount of time has passed, or when the runtime sees available memory getting low), so objects are not necessarily released at the exact moment they are no longer been used.


Advantages of Garbage Collection
  • GC can clean up entire object graphs, including retain cycles. This is the primary advantage of the garbage collection over ARC that you don't need to be worry about retain cycles.
  • GC happens in the background, so less memory management work is done as part of the regular application flow.
Disadvantages of Garbage Collection
  • Because GC happens in the background, the exact time frame for object releases is undetermined.
  • When a GC happens, other threads in the application may be temporarily put on hold.

Automatic Reference Counting

ARC is a compiler feature uses object-ownership. Instead of looking for unused objects in the background during runtime, ARC releases the objects from the memory if the object has reference count of zero meaning it has no owner anymore. ARC automatically injects Objective-C runtime equivalents for retain, release (the compiler inserts retains and releases in all the places you should have) at compile time. I have a post explaining how this works.


Advantages of Automatic Reference Counting
  • Destruction of the objects is real-time, an predictable. It has deterministic reclamation of objects (when the last strong reference to the object goes away) where GC frees an object "sometime later". Objects are released as soon as they can no longer be referenced without long pauses for collection cycles. This make the objects to be released sooner. It is important for the systems with limited memory such as mobile devices.
    This defines away a class of subtle bugs that can exist in GC apps that aren't exposed because the collector doesn't trigger "in the buggy window".

  • No background processing, which makes it more efficient again for lower-power systems.

  • Tracing garbage collection cycles are triggered too often if the set of live objects fills most of the available memory, it requires extra space to be efficient. Reference counting performance does not deteriorate as the total amount of free space decreases.

  • Asymptotic complexity of reference counting does not depend upon the total size of the heap.

Disadvantages of Automatic Reference Counting
  • Cannot collect retain cycles. Retain cycles keep reference counts above zero even when they are unreachable

  • Multithreaded reference counting need to be considered.



Further Study








Friday, August 18, 2017

Swift Memory Management

A well memory managed app doesn't take up any extra space than it needs. Finding memory leaks in an app is not easy, instead understanding the way iOS memory management works is trivial. In this article I tried to clarify how and when memory allocation and deallocation happens in iOS specifically in Swift. And I also tried to give an overview of retain cycles which is one of the most common causes of the memory leaks.


ARC

Swift inherited its memory management system from Objective-C which is called ARC, Automatic Reference Counting. ARC uses object ownership concept which means it destroys the objects and releases them from the memory if the object has no owner anymore.

  • Reference count: In order to manage the object ownerships, ARC uses a concept called reference count. Claiming an ownership of an object, increases the reference count of that object by one. As soon as the reference count comes down to zero, the object will be released.
  • Strong reference claims the ownership of the object and increments the reference count. As long as someone has a strong reference to an object, ARC will not generate the release message for the object and it won't be released. In Swift all the references are strong if not specified.
  • Weak: If an object is created using weak keyword, it has no owner.

If you're still not comfortable with the strong vs. weak concept, think of the object as balloons (this is the best explanation I've ever seen for this subject, many thanks to Martin for this clear simplification). A balloon won't fly away (released) as long as at least one person is holding a string to it. The number of people holding strings is the retain count. Many people can have strings to the same balloon. A strong reference is like holding on to a string to that balloon. As long as you are holding on to a string attached to the balloon, it will not fly away. A weak reference is like looking at the balloon. You can see it, access its properties, call its methods, but you have no string to it. If everyone holding onto the string releases the balloon, it flies away.


Retain Cycle

Retain Cycle or Strong reference cycle happens when two objects have strong references to each other. Their reference counts never go to zero so they never get deallocated. Retain cycle happens with different scenarios. Here is a list of most common ones:

  1. Hierarchical relationships
    Parent class should always have a strong reference to its child classes (this a is convention not a rule, all we have to be sure about is that we are not making a two way strong references, it should be either parent to child or child to parent). When a child wants a reference to its parent, though, it should make it a weak reference by using the weak keyword. In simpler words object must never retain its parent or any hierarchical ancestor.

  2. Mutually dependent objects
    When two objects have reference to each other, one should use weak reference to avoid the retain cycle. You can find the famous example of Tenant-Apartment in Swift documentations.

  3. Closures
    If any variable is declared outside of the closure's scope, referencing that variable inside the closure's scope creates another strong reference to that object (except Ints, Strings, Arrays, and Dictionaries in Swift because they are value types). In other words, class retains a closure that captures self strongly.
    Capture list defines how the variable references are captured in the closure. By default, if you don't use a capture list, everything will be strongly referenced. To avoid retain cycle, use weak or unowned reference to self in closure's capture list.

  4. Delegates
    Usage of Delegates can cause a retain cycle if the delegate is not set to be weak 
    because most delegates are referencing classes that they do not own.

weak and unowned Keywords

The purpose of using the weak and unowned keyword is to avoid strong reference cyclesBoth of them do not increase the reference count of the object being referred and will assign an instance without keeping a strong reference to it. 

weak is used when you know that reference is allowed to become nil so it has to be defined as an optional variable. They will be mutated to nil after deallocation.

unowned 
is used when you are certain that reference will never become nil so it has to be defined as non-optional since it is assumed to always have a value.

Here there are few lines I found helpful from Swift documentations: Use an unowned reference only when you are sure that the reference always refers to an instance that has not been deallocated. If you try to access the value of an unowned reference after that instance has been deallocated, you’ll get a runtime error.


Which one to use?
When two instances are optionally related to each other weak is the right option.
There are times when two class instances are related to one another, but one of those instances cannot exist without the other one (e.g. area code for a phone number). They are mutually dependent, so they will always be deallocated at the same time. This is the case unowned should be used.


Reference types vs. Value types

Struct and Enum are value types means when a new instance is made, their values are copied instead of increasing its reference count, so they don't make strong reference cycles. It means that if you are dealing with value types you don’t even need to worry about specifying strong or weak for them.




Further Study

Automatic Reference Counting 
Interview Questions: How is memory management handled on iOS?
Retain Cycles, Weak and Unowned in Swift
"Weak, Strong, Unowned, Oh My!" - A Guide to References in Swift
Strong, Weak, and Unowned – Sorting out ARC and Swift 
Capture List


Tuesday, May 2, 2017

Object Oriented Principals in plain language


Keep it simple

If you know how to write code in a Object Oriented language, you probably know how to implement its primitive concepts, you know how to declare a method as private or how to subclass from a class. But can we explain what Polymorphism is in plain English? Or what if during an interview you are asked about Abstraction, what do you say? Here is a simple reasonable explanation of each in case you are asked in an interview:


Inheritance:

Inheritance allows us to subclass from a class. In object oriented programming classes are all members of hierarchy classes and that is possible with Inheritance principle.
Child class inherits methods and properties form the parent. This enables the developers to reuse the code easily.

Abstraction: 

Abstraction means representing essential features without including implementations. What does that mean? Abstraction is a concept or paradigm of describing things in simpler terms (abstract details) depending on its location in inheritance hierarchy. It helps representing essential features without being worried about the implementation. At the most abstract level there is no implementation details. More abstract concepts are at the top and more concrete ideas go to the bottom. This graph represent a general idea of abstraction concept:







Interface is a set of methods with no implementations. Abstract classes contain both abstract and concrete methods and they must be inherited.


Encapsulation:


Encapsulation is used to define, hide and restrict properties and methods outside access. It prevents unnecessary access to methods and properties (class is container encapsulating the data). The access is available only if required, this handles by access modifiers:

  • Public: Accessible from everywhere
  • Protected: Accessible within the same package and subclasses
  • Default (no specifier): Accessible form inside the package
  • Private: Only accessible within the same class, not visible to subclasses




Public Protected Default Private
Class ✔️ ✔️ ✔️ ✔️
Package ✔️ ✔️ ✔️
Subclass(Same Package) ✔️ ✔️ ✔️
Subclass(Different Package) ✔️ ✔️
World ✔️



Polymorphism:

Polymorphism give us availability to define a method (in subclass) that is already declared in the parent class. Generally there are two types of polymorphism: 
  • Compile time polymorphism or overloading:
    You can define several methods with the same name, the only difference will be the method signatures.
  • Run time polymorphism or overriding: 
    You can define methods with the same name and signature as parent class (or the implemented interface). This gives us ability to define the methods that is specific to particular subclass. 

If you have OOP keyword on your resume, you should be able to explain these concepts but not limited to these four.