título: creador-recursos para la detección de fugas
categorías: Cocos2dx
etiquetas: [creador, optimización, fuga, memoria]
fecha: 2023-03-29 14:48:48
comentarios: falso
mathjax: verdadero
toc: verdadero
creador-Recursos de detección de fugas
precuela
-
Lanzamiento de recursos: https://docs.cocos.com/creator/manual/zh/asset/release-manager.html
-
Antes de ejecutar pruebas relevantes y tomar instantáneas, asegúrese de ejecutar gc js varias veces
Código para información de volcado relevante
-
vertedero
public dumpPath(path: string) { let bundleName = "resources" let bundle = assetManager.getBundle(bundleName); let asset01 = bundle.get(path); let uuid = asset01._uuid this.dumpUuidRecur(uuid) } private dumpUuidRecur(uuid: string, depth: number = 1) { let pre = "---".repeat(depth) var asset01 = assetManager.assets.get(uuid)!; var uuids: string[] = assetManager.dependUtil.getDepsRecursively(uuid)!; LogUtil.D(`${ pre} dumpUuidRecur: ${ uuid}, refCnt: ${ asset01.refCount}\nasset:`, asset01, "\nuuid:", uuids) uuids.forEach(uuid => { this.dumpUuidRecur(uuid, ++depth) }); } public dump() { assetManager.assets.forEach((value: Asset, key: string) => { console.log(assetManager.assets.get(key)); }) console.log(`当前资源总数:${ assetManager.assets.count}`); }
Carga estática: varios prefabricados se refieren a la misma imagen
-
Hice dos de los prefabricados más simples, que se refieren a la misma imagen.
-
Ejecutar carga dinámica
-
Echa un vistazo a la información de recursos de estos dos caminos prefabricados
-
Se encontró que spriteFrame mantiene recuentos de referencias, texture2d e imageAsset no mantienen recuentos de referencias
Según la documentación de Guanfan: https://docs.cocos.com/creator/manual/zh/asset/release-manager.html#%E8%B5%84%E6%BA%90%E7%9A%84%E9% 9D%99%E6%80%81%E5%BC%95%E7%94%A8
Solo necesitamos mantener el recuento de referencias prefabricadas -1, el motor mantendrá la tecnología de referencia spriteFrame y luego mantendrá texture2d e imageAsset, spriteFrame es equivalente al Material en la imagen de la derecha
-
Recuento de referencia -1 cuando se destruye la casa prefabricada
-
En el caso de que no se cargue ningún prefabricado, la cantidad total es 55
-
Cuando se cargan prefabricados, la cantidad total es 60
-
Destruya el prefabricado, y el recuento de referencia del prefabricado es -1, y el número total vuelve a 55.
El recurso es normal
Carga dinámica: correcta
-
En el caso de que no se cargue ningún prefabricado, la cantidad total es 55
-
Después de cargar el prefabricado, cargue dinámicamente una imagen de big002 y el recuento de referencia +1, total 63
-
Destruya el prefabricado, y el recuento de referencia del prefabricado es -1, y el recuento de referencia de recursos de los recursos cargados dinámicamente es -1, y el número total vuelve a 55.
El recurso es normal¡¡¡La clave aquí es mantener el recuento de referencia de los recursos cargados dinámicamente por ti mismo!!!
Carga dinámica: error
-
En el caso de que no se cargue ningún prefabricado, la cantidad total es 55
-
Después de cargar el prefabricado, cargue dinámicamente una imagen de big002 (no opere el conteo de referencia), el número total es 63
-
Destruir el prefabricado, la cantidad total no ha vuelto a 55
recursos no es normalAl ver que, aunque el recuento de referencias de big002 spriteFrame es 0, ¿por qué no se ha publicado todavía? Como resultado, el texture2d asociado y el imageAsset no se han publicado
El activador de cocos se activa mediante el método de disminución del recuento de referencia por decRef, todo lo cual aún debe llamarse manualmente para liberar
-
3.7.1 Código fuente relacionado
-
El seguimiento de recursos mantiene automáticamente los recuentos de referencia
Después de conocer las reglas de publicación, puede agregar un rastreador al administrador de recursos personalizado, para que los recursos cargados mantengan automáticamente los recursos cargados relevantes de acuerdo con el final del ciclo de vida del nodo, para que los desarrolladores no tengan que preocuparse. sobre problemas de conteo de referencias, solo se preocupan por la generación y destrucción de nodos
-
De hecho, el principio es muy simple, que consiste en colgar un componente en el nodo para registrar los recursos durante la carga, a fin de mantener el recuento de referencia.
-
AssetTracker.ts
import { _decorator, Component, Node, Asset, SpriteFrame } from 'cc'; import { LogUtil } from '../log/LogUtil'; const { ccclass, property } = _decorator; @ccclass('AssetTracker') export class AssetTracker extends Component { public static trace(go: Node, ast: Asset) { let at = go.getComponent(AssetTracker) if (!at) { at = go.addComponent(AssetTracker) } at.traceInner(ast) } private _astArr = new Array<Asset>() traceInner(ast: Asset) { ast.addRef() this._astArr.push(ast) } onDestroy() { // LogUtil.D(`--- onDestroy, cnt: ${this._astArr.length}, _astArr:\n`, this._astArr) this._astArr.forEach((ast, idx, arr) => { ast.decRef() }) this._astArr = null } debugDump() { this._astArr.forEach((ast, idx, arr) => { LogUtil.D("", ast) }) } }
-
-
Ejemplo de interfaz de carga relacionada
// ------------------------------------ 对外接口 begin public async instantiateAsync(prefabPath: string, parent?: Node) { return new Promise<Node>((resolve) => { this.load(prefabPath, (err: Error, asset: Prefab) => { if (err) { LogUtil.E(`--- instantiateAsync error, path: ${ prefabPath}, err:`, err) resolve(null) return } let go = instantiate(asset); AssetTracker.trace(go, asset) // 资源计数追踪 if (parent) go.parent = parent resolve(go) }) }) } // refGo 挂点, 最好是资源要依附的节点 public async loadAssetAsync<T extends Asset>(assetPath: string, refGo: Node) { return new Promise<T>((resolve) => { this.load(assetPath, (err: Error, asset: T) => { if (err) { LogUtil.E(`--- loadAssetAsync error, path: ${ assetPath}, err:`, err) resolve(null) return } AssetTracker.trace(refGo, asset) // 资源计数追踪 resolve(asset) }) }) } // refGo 挂点, 最好是资源要依附的节点 public async loadRemoteAsync<T extends Asset>(url: string, opts: IRemoteOptions, refGo: Node) { return new Promise<T>((resolve) => { this.loadRemote(url, opts, (err: Error, asset: T) => { if (err) { LogUtil.E(`--- loadRemoteAsync error, url: ${ url}, err:`, err) resolve(null) return } AssetTracker.trace(refGo, asset) // 资源计数追踪 resolve(asset) }) }) } // ------------------------------------ 对外接口 end
Medido
-
Cuando el prefabricado no está cargado, el número total es 55, y la memoria y el caché de imágenes son los siguientes
-
En el caso de cargar imágenes prefabricadas y dinámicamente, el número total es 61, y la memoria y el caché de imágenes son los siguientes
-
Destruya los nodos prefabricados, el número total vuelve a 55, y la memoria y el caché de imágenes también vuelven al valor inicial, lo que indica que los recursos se liberan normalmente.