Loading UIImage's on background thread solves SceneKit memory problems. Why?
Consider the following code:
let img = UIImage(named: "myString")
if let img = img {
mySCNMaterial.diffuse.contents = img
}
I was using this to load images in a SceneKit project. Specifically, I was doing this from inside my UIViewController
's viewDidLoad
.
As long as I was doing it this way, my project was leaking memory like crazy (restarting a level in the game would bump memory consumption up by something like 30mb each time, and that memory would never be reclaimed). However, Instruments
found no memory leaks, and enabling my project scheme's Zombie Objects
gave results that were...literally unbelievable, with something like 1000+ zombies from all kinds of sources.
At some point, I learned about the difference between UIImage(named:)
and UIImage(contentsOfFile:)
, with the system caching the former, but not the latter.
So, now I've got this:
let path = Bundle.main.path(forResource: "myString", ofType: "png")!
let img = UIImage(contentsOfFile: path)!
mySCNMaterial.diffuse.contents = img
I theorized that this would improve memory usage in my own game, but the gains were minimal at best.
But today I decided to try explicitly running the previous bit of code on a background thread (UIImage
is thread-safe, according to the documentation) -- and my game stopped leaking memory entirely, as determined by the Instruments
Allocations
template.
So, now I've got this:
DispatchQueue.global(qos: .background).async {
let path = Bundle.main.path(forResource: "myString", ofType: "png")!
let img = UIImage(contentsOfFile: path)!
mySCNMaterial.diffuse.contents = img
}
While I'm very glad to have stumbled upon this fix, I'd开发者_Go百科 like to better understand what's going on.
Question: Why might these changes solve my SceneKit game's memory usage problems?
精彩评论