Utilize the power of multiple Cores on iOS App

Ankur JAIN
Analytics Vidhya
Published in
7 min readSep 17, 2020

--

Source — https://pixabay.com/illustrations/physics-quantum-physics-particles-3873118/

Concurrency is achieved when the app is capable to run multiple tasks at the same time. Latest A13 Bionic comes with 6 cores which means that it has the capacity to execute 6 tasks at a time. Yes, one core can execute at-most one task at at time. To learn more about the cores, please go through Cores

All the latest iphones has the capacity to run multiple tasks at a time which improves the performance of the app. But how does it do that? Let’s understand this in this post.

When we tap on the app icon on the home screen on our phone, a program gets executed by our operating system (OS will have all the addresses and meta data to launch the program after the app gets installed). Then this program creates process to start the execution which starts with the initial point(in iOS it’s called main.m). During the lifetime of this process, it may creates many threads (smallest sequence of instructions to be executed by the cores). Let’s understand these terminologies first -

Thread

In very simple words, it’s a smallest sequence of instructions which gets executed by the cores available on the device.

Above code shows how we create a seperate thread to execute some code in getData method. As the scope of this thread is at the method level, it will be destroyed by the OS as soon as it completes getData()

The app starts with Main Thread which executes all the UI level instructions and also manages some background threads to execute background tasks. I would highly recommend you to go through Threads in deep as it will help you understand how iOS schedules and execute tasks on multiple cores at a time. To read more about Threads please go through- Threads

Process

A process is the one which creates and manages all the threads required to execute a program. Consider a facebook app on our iphone. On the OS level, it’s stored as a program and when we launch it, it creates a process which in-turn creates threads to run our instructions. So a process can have multiple threads running a the same time and in a similar way, a program can have multiple processes running at the same time.

So the finals words are — A process creates or managess one or more threads to execute the instructions. A program creates or manages one or more process to start and run the program till it’s completion.

An iOS app is a program which, when launched, creates a process that creates and manages threads to execute the instructions in our code. Our app comes with One Main Thread that executes all the UI level tasks and mostly runs on high performance cores (every processor has some high performance cores). iOS gives us options to create other threads to run our code in background to acheive better performance because if those background tasks are run on the same main thread, our UI will get unresponsive for the time the other tasks get executed.

iOS gives some high level abstractions too to create and handle threads. Example are — GCD (Grand Central Dispatch), Operation Queues.

Grand Central Dispatch (GCD)

It’s similiar C’s libdispatch library. It’s purpose is to queue up tasks (piece of code e.g. method or closure) that can be run in parallel by the available cores. GCD is built upon the Threads API so it does all the work the same way but we don’t have to worry about creating and managing Threads, which saves a lot of effort and time. Pass a closure and GCD will take care of executing it with the attached thread.We can enqueue n number of tasks to a queue but they are executed FIFO(First in First Out). These queues will have a pool of threads attached managed by the OS.

Serial Queues have one thread attached and Concurrent queues can have as many threads as the system has resources for to run tasks in parallel.

Even GCD start execution of the tasks in FIFO but it doesn’t ensure that the tasks will finish in the order we submit them, rather this depends on the task’s complexity and the time it can take.

There’re two types of Queues that iOS provides to execute our tasks in parallel

  1. Serial Queues
  2. Concurrent Queues

Serial Queues

Serial queues has only single thread associated with them and thus allows a single task to be executed at a given time. Our App runs on a Serial Queue which is called Main Queue. All the UI level operations run on this queue and if we execute any other task in the same queue, our UI might get unresponsive until the other tasks gets completed. So it’s highly recommended to use main queue only for UI related stuff.

Concurrent Queues

A concurrent queue, on the other hand, is able to utilize as many threads as the system has resources for. Threads will be created and released as necessary on a concurrent queue.

Note: While you can tell iOS that you’d like to use a concurrent queue, remember that there is no guarantee that more than one task will run at a time. If your iOS device is completely bogged down and your app is competing for resources, it may only be capable of running a single task.

Example of a Serial Queue

As you can see, three blocks of code are asynchrounously enqueued in the serial queue and the result shows that the second tasks start only when the first is finished and same goes for 2nd and 3rd.

Example of a Concurrent Queue

In this example, a we enqueue three blocks to execute and the results shows that the 2nd and 3rd tasks starts executing before even the first is finished. This means that the task will be executed concurrently on different cores.

I can’t cover GCD in full in this post, probably will write a separate one just to explain GCD and it’s terminologies. If you’re eager to learn more, go through the official documention for the same- Queues

Asynchronous doesn’t mean concurrent

While the difference seems subtle at first, just because your tasks are asynchronous doesn’t mean they will run concurrently. You’re actually able to submit asynchronous tasks to either a serial queue or a concurrent queue. Being synchronous or asynchronous simply identifies whether or not the queue on which you’re running the task must wait for the task to complete before it can spawn the next task.
On the other hand, categorizing something as serial versus concurrent identifies whether the queue has a single thread or multiple threads available to it. If you think about it, submitting three asynchronous tasks to a serial queue means that each task has to completely finish before the next task is able to start as there is only one thread available.
In other words, a task being synchronous or not speaks to the source of the task. Being serial or concurrent speaks to the destination of the task.

Operations

Just like GCD, Operations and OperationQueue are the highest level of abstraction to achieve concurrency in our app. Operations are fully-functional classes that can be submitted to an OperationQueue, just like you’d submit a closure of work to a DispatchQueue for GCD. Because they’re classes and can contain variables, you gain the ability to know what state the operation is in at any given point.

At a time, a operation can be in any of these state-

  1. isReady
  2. isExecuting
  3. isCancelled
  4. isFinished

Each state’s name explain the current status of the operation.

Point to note here is, if an operation is in isExecuting state and we set isCancelled to true that doesn’t mean that the operation will be immediately cancelled. It’ll just set the property to isCancelled.

Operations provide greater control over your tasks as you can now handle such common needs as cancelling the task, reporting the state of the task, wrapping asynchronous tasks into an operation and specifying dependencies between various tasks. I’m not going in deep about operations but you can read about them right here- OperationQueues

Conclusion

To make performant and powerful apps, Concurrent programming becomes the most important subject to learn. Even though iOS provides higher level abstractions like GCD and Operations, it becomes really important to know how and when to use them. I would suggest everyone if they are new to iOS development, to go through GCD, Operations in detail and also learn how and when these abstractions work best. It’s equally important to learn how the threading works underneath to understand the low level execution for making better decisions. There’re other important terminologies like Semaphores, Groups and Locks which we should know but I’m keeping them for another post.

Thanks For Reading 😀

Bye 👋

--

--