Clean up app resources without bottleneck

Hai Kieu
Hai Kieu
Aug 7 · 4 min read

Complexity of discarded resources

I begin the story in a simple scope. There is an array which has 100 objects in it

//Create an array
for _ in 1...100 {
let newObject = Object()
array.append(newObject)
}
//Clean up resources
array.removeAll()

Cleaning up the array of 100 objects is not a big deal.

Continue develop the complexity, I assume that each object has 10 properties. Each property is some kind of object.

//Clean up 100 objectsarray.removeAll() //How many objects will be deallocated eventually?

Let do a simple calculation. Each object needs to deallocate 10 of its properties, so free 100 objects will actually deallocate 1000 objects.

This begins to take significant time.

Continue develop the complexity, I assume each object has 10 child objects and each child has 10 grand-child objects.

Assuming We have an array with 100 objects of this type, so We really has 2 dimensions table. How many objects will be freed when cleaning up the array?

10.000 objects

It is vary in situations. It can be 10 thousands of message objects, 10 thousands of emails, 10 thousands of books, 10 thousands of metadata objects, 10 thousands of songs, 10 thousands of customer records, and so on.

So, getting rid of 10 thousands object is enough to make a trouble?

Review a scenario in app

Assuming, the left picture is the logout of a chat app.

During the user session, hundred of conversations between users, thousands of messages per each conversation are generated.

When logging out, What We must do is remove all the messages, conversations and stuffs from memory.

Look at the log-out method below


//There are 100 conversation objects, and 10.000 message objects per each conversation.
func logOut() { //How many objects will be freed actually after this?
conversations = []
}

This method will free 1.000.000 objects. In the worst case, What issue would happen? Check this out

Observing FPS, We see it drops below 30 frames. It means user see app freeze for a while.

Why?

Why the FPS drops under 30 frames? To understand the issue, I put this below piece of code in either Conversation class or Message class.

deinit {  print("Deallocating on mainThread=\(Thread.current.isMainThread)")
}

In runtime, I believe it says “Deallocating on mainThread=true”

Is deallocating resources neccessary to happen on MainThread?

Resolve issue with DumpTruck

The issue we have seen here is it bottlenecks the MainThread. This end up dropping the FPS. This is bad.

Okay, now let see how to resolve the issue. In below piece of code, I’m giving a utility class which helps resolve the bottleneck. I call it “DumpTruck”.

///What the DumpTruck does is clean up resources in background threadfinal class DumpTruck { static func empty(_ object: Any?) {    var capture = [object]    DispatchQueue.global().async {      //Clean up memory take place here
capture.removeAll()
}
}
}

Now, let give the DumpTruck a call

func logOutWithDumpTruck() {  //Ask DumpTruck to empty the conversations
DumpTruck.empty(conversations)
//Remove tie to the removed conversations
self.conversations = []
}

Run and see the outcome. It should be good. Trust me.

Observing the FPS, no frame drop at all.

Conclude

In the above DumpTruck class, I hope I give you an initial idea how to deal with cleaning up app resources properly. That is make the cleanup happened on background.

Which cases need DumpTruck help? Actually, not everything. Removing a few objects is not worthy to give DumpTruck a call. Let consider these cases: Array, Stack, Queue, Dictionary, or anything like that.

One more important thing, We need to differentiate non-UI object and UI object. Dealing with non-UI object is easy. However a UI object does not behave like that. The UI object is more headstrong, it will not let you dispatch it to background anyway.

Deallocation of any UI object like UIView or UIViewController always happen on Main-Thread. Does it bottleneck MainThread? In the worst case, I think it is YES. To deal with that We need a special type of strategy. It could be next story I share, so stay tuned.

Source code

https://github.com/haikieu/Demo-Clean-Up-Memory

This story origin is from swiftreviewer.com

Hai Kieu

Written by

Hai Kieu

Senior developer. Been working on iOS, tvOS, Swift, and Objective-C

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade