Я испытываю снижение производительности при предварительной загрузке SKTextureAtlas
:
let textureAtlas = SKTextureAtlas(named: atlasName)
textureAtlas.preload(completionHandler: {
...
})
Под падением производительности я имею в виду падение FPS до ~ 50 на короткое время.
Я протестировал его с Time Profiler
в Instruments
и убедился, что эта работа действительно выполняется в рабочем потоке, как указано в документация.
На изображении ниже показан Time Profiler
снимок всплеска, вызванный предварительной загрузкой атласа. Как видите, большая часть всплеска вызвана двумя рабочими потоками, которые, насколько я понимаю, загружают данные изображения. Однако это не должно привести к снижению производительности основного потока IMHO.
Примечание 1. .spriteatlas
, которые я предварительно загружаю, не так уж и много: 4 ресурса с прибл. 1000x1000
размер.
Примечание 2. Я тестирую с iPhone 6, iOS 10, Xcode 8.
Примечание 3. В то же время не ведется никакой другой существенной работы; Процессор все время зависает на ~30%. То же самое касается графического процессора.
Примечание 4. Предварительная загрузка атласа запрашивается задолго до того, как потребуется любая из текстур из этого атласа, поэтому времени для предварительной загрузки должно быть более чем достаточно.
Любая помощь/направление с благодарностью!
ОБНОВЛЕНИЕ
Полный блок кода, где происходит предварительная загрузка:
let updateGroup = DispatchGroup()
for assetDefinition in assetContainmentDefinitions {
let assetName = assetDefinition.assetName
// Check if asset is not needed anymore and clear the cache with it
if progress >= assetDefinition.range.to {
if cachedAssets[assetName] != nil {
cachedAssets[assetName] = nil
}
}
// Check if asset is needed and if it's not already loading then preload and cache it
else if progress >= assetDefinition.range.from {
if currentlyLoadingAssets.contains(assetName) == false &&
cachedAssets[assetName] == nil {
currentlyLoadingAssets.append(assetName)
// Enter dispatch group
updateGroup.enter()
switch assetDefinition.assetType {
case .textureAtlas:
let textureAtlas = SKTextureAtlas(named: assetName)
textureAtlas.preload(completionHandler: {
DispatchQueue.main.async { [weak self] in
self?.cachedAssets[assetName] = textureAtlas
self?.currentlyLoadingAssets.remove(object: assetName)
// Leave dispatch group after preload is done
updateGroup.leave()
}
})
case .texture:
let texture = SKTexture(imageNamed: assetName)
texture.preload(completionHandler: {
DispatchQueue.main.async { [weak self] in
self?.cachedAssets[assetName] = texture
self?.currentlyLoadingAssets.remove(object: assetName)
// Leave dispatch group after preload is done
updateGroup.leave()
}
})
}
}
}
}
// Call completion after the dispatch group is fully completed
if let completion = completion {
updateGroup.notify(queue: DispatchQueue.main, execute: completion)
}
ОБНОВЛЕНИЕ 2
Я создал пустой проект только с блоком предварительной загрузки атласа. Падение производительности все равно происходит. Я пробовал с несколькими атласами, даже с атласом только с одним активом.
Я также пробовал то, что предложил @Sez (см. ниже), в этом пустом новом проекте, но в этом случае блок завершения даже не вызывался, что похоже на еще одну ошибку в классе SKTextureAtlas
. (?!)
let atlas = SKTextureAtlas(dictionary: ["texture1": UIImage(named: "texture1")!])
atlas.preload(completionHandler: { [weak self] in
print("COMPLETION BLOCK NOT CALLED")
self?.cachedAtlas = atlas
})
ОБНОВЛЕНИЕ 3
Я попытался удалить .spriteatlas
и создать .atlas
с теми же текстурами, и производительность (почти) не упала. Однако .atlas
не поддерживает нарезку, поэтому я хочу использовать .spriteatlas
в первую очередь.
atlas.preload(completionHandler:)
, и у меня все еще возникает та же проблема. Пробовал с разными атласами. - person damirstuhec   schedule 01.12.2016