versionflow release性能优化

This commit is contained in:
ALIENJACK\alien 2025-08-20 13:15:38 +08:00
parent 712b303858
commit e8c9abd219
3 changed files with 109 additions and 63 deletions

View File

@ -27,6 +27,7 @@ namespace VersionFlow.Runtime
public List<string> Assets { get; private set; } public List<string> Assets { get; private set; }
/// <summary> 此AB所在Chain </summary> /// <summary> 此AB所在Chain </summary>
internal HashSet<LoadingChain> m_inChains = new HashSet<LoadingChain>(); internal HashSet<LoadingChain> m_inChains = new HashSet<LoadingChain>();
internal static Dictionary<Object, ABEntity> s_AssetToABMapper = new Dictionary<Object, ABEntity>();
public ABEntity(Bundle bundle, bool isDownloaded) public ABEntity(Bundle bundle, bool isDownloaded)
{ {
@ -191,6 +192,7 @@ namespace VersionFlow.Runtime
if (!m_assetRefCount.ContainsKey(result)) if (!m_assetRefCount.ContainsKey(result))
{ {
m_assetRefCount[result] = 1; m_assetRefCount[result] = 1;
s_AssetToABMapper[result] = this;
OnAssetLoad?.Invoke(this, result); OnAssetLoad?.Invoke(this, result);
} }
else m_assetRefCount[result]++; else m_assetRefCount[result]++;
@ -221,6 +223,7 @@ namespace VersionFlow.Runtime
if (!m_assetRefCount.ContainsKey(result)) if (!m_assetRefCount.ContainsKey(result))
{ {
m_assetRefCount[result] = 1; m_assetRefCount[result] = 1;
s_AssetToABMapper[result] = this;
OnAssetLoad?.Invoke(this, result); OnAssetLoad?.Invoke(this, result);
#if UNITY_EDITOR #if UNITY_EDITOR
@ -245,6 +248,8 @@ namespace VersionFlow.Runtime
{ {
m_assetRefCount.Remove(asset); m_assetRefCount.Remove(asset);
OnAssetUnLoad?.Invoke(this, asset); OnAssetUnLoad?.Invoke(this, asset);
s_AssetToABMapper.Remove(asset);
if (asset is not GameObject) if (asset is not GameObject)
Resources.UnloadAsset(asset); Resources.UnloadAsset(asset);

View File

@ -23,14 +23,14 @@ namespace VersionFlow.Runtime
/// <summary> shader变体收集器 </summary> /// <summary> shader变体收集器 </summary>
public ShaderVariantCollection SVC { get; private set; } public ShaderVariantCollection SVC { get; private set; }
private readonly HashSet<LoadingChain> m_loadingChains = new HashSet<LoadingChain>(); private readonly Dictionary<ABEntity, LoadingChain> m_loadingChains = new Dictionary<ABEntity, LoadingChain>();
private readonly Type m_gameObjectType = typeof(GameObject); private readonly Type m_gameObjectType = typeof(GameObject);
/// <summary> 可选Bundle组:ABEntity </summary> /// <summary> 可选Bundle组:ABEntity </summary>
private readonly Dictionary<string, OptionalBundleDownloader> m_optionGroupDownloader = new Dictionary<string, OptionalBundleDownloader>(); private readonly Dictionary<string, OptionalBundleDownloader> m_optionGroupDownloader = new Dictionary<string, OptionalBundleDownloader>();
public string Version { get; set; } = "N/A"; public string Version { get; set; } = "N/A";
internal HashSet<LoadingChain> GetLoadingChains() => m_loadingChains; internal IEnumerable<LoadingChain> GetLoadingChains() => m_loadingChains.Values;
internal BundleManager(BundleManifest local, BundleManifest remote) internal BundleManager(BundleManifest local, BundleManifest remote)
{ {
@ -109,6 +109,21 @@ namespace VersionFlow.Runtime
} }
} }
internal ABEntity GetEntityByAsset(UnityEngine.Object asset)
{
ABEntity.s_AssetToABMapper.TryGetValue(asset, out var entity);
return entity;
}
internal LoadingChain GetLoadingChainByAsset(UnityEngine.Object asset)
{
var ab = GetEntityByAsset(asset);
if (ab == null) return null;
m_loadingChains.TryGetValue(ab, out var chain);
return chain;
}
internal ABEntity GetEntityByAssetPath(string assetPath) internal ABEntity GetEntityByAssetPath(string assetPath)
{ {
m_assetPathToAB.TryGetValue(assetPath, out var bundle); m_assetPathToAB.TryGetValue(assetPath, out var bundle);
@ -164,18 +179,10 @@ namespace VersionFlow.Runtime
internal LoadingChain GetLoadChain(ABEntity ab, bool shaderOnly) internal LoadingChain GetLoadChain(ABEntity ab, bool shaderOnly)
{ {
LoadingChain targetChain = null; LoadingChain targetChain = null;
foreach (var chain in m_loadingChains) if (!m_loadingChains.TryGetValue(ab, out targetChain))
{
if (chain.m_topEntity == ab)
{
targetChain = chain;
break;
}
}
if (targetChain == null)
{ {
targetChain = LoadingChain.Create(ab, shaderOnly); targetChain = LoadingChain.Create(ab, shaderOnly);
m_loadingChains.Add(targetChain); m_loadingChains[ab] = targetChain;
} }
return targetChain; return targetChain;
@ -203,7 +210,7 @@ namespace VersionFlow.Runtime
//找到已加载场景的loadchain //找到已加载场景的loadchain
LoadingChain hasSceneChain = null; LoadingChain hasSceneChain = null;
foreach (var chain in m_loadingChains) foreach (var chain in m_loadingChains.Values)
{ {
if (chain.m_currentLoadScenePath != null) if (chain.m_currentLoadScenePath != null)
{ {
@ -238,7 +245,7 @@ namespace VersionFlow.Runtime
//找到已加载场景的loadchain //找到已加载场景的loadchain
LoadingChain hasSceneChain = null; LoadingChain hasSceneChain = null;
foreach (var chain in m_loadingChains) foreach (var chain in m_loadingChains.Values)
{ {
if (chain.m_currentLoadScenePath != null) if (chain.m_currentLoadScenePath != null)
{ {
@ -379,9 +386,10 @@ namespace VersionFlow.Runtime
} }
else else
{ {
foreach (var chain in m_loadingChains) var ab = GetEntityByAsset(asset);
if (ab != null)
{ {
chain.UnLoadAsset(asset); ab.UnLoadAsset(asset);
} }
asset = null; asset = null;
@ -403,7 +411,7 @@ namespace VersionFlow.Runtime
assetList.Clear(); assetList.Clear();
} }
HashSet<LoadingChain> m_needRemoveChains = new HashSet<LoadingChain>(); HashSet<ABEntity> m_needRemoveChains = new HashSet<ABEntity>();
/// <summary> /// <summary>
/// 检查已加载的Bundle的引用计数为0并且没有任何依赖bundle被加载 /// 检查已加载的Bundle的引用计数为0并且没有任何依赖bundle被加载
/// 然后移除它 /// 然后移除它
@ -417,13 +425,16 @@ namespace VersionFlow.Runtime
m_needRemoveChains.Clear(); m_needRemoveChains.Clear();
foreach (var chain in m_loadingChains) foreach (var item in m_loadingChains)
{ {
if (chain.TryDispose()) var topAB = item.Key;
m_needRemoveChains.Add(chain); var chain = item.Value;
}
m_loadingChains.ExceptWith(m_needRemoveChains); if (chain.TryDispose())
m_needRemoveChains.Add(topAB);
}
foreach (var removeChainKey in m_needRemoveChains)
m_loadingChains.Remove(removeChainKey);
} }
/// <summary> /// <summary>

View File

@ -50,8 +50,31 @@ namespace VersionFlow.Runtime
} }
} }
void Entity_OnAssetLoad(ABEntity sender, Object asset) => m_loadedAssets[asset] = sender; void Entity_OnAssetLoad(ABEntity sender, Object asset)
void Entity_OnAssetUnLoad(ABEntity sender, Object asset) => m_loadedAssets.Remove(asset); {
m_loadedAssets[asset] = sender;
}
void Entity_OnAssetUnLoad(ABEntity sender, Object asset)
{
m_loadedAssets.Remove(asset);
if (asset is GameObject prefabSrc)
{
m_prefabSrcToInstance.Remove(prefabSrc);
string needRemoveKey = null;
foreach (var item in prefabSrcCache)
{
if (item.Value == prefabSrc)
{
needRemoveKey = item.Key;
break;
}
}
if (needRemoveKey != null)
prefabSrcCache.Remove(needRemoveKey);
}
}
internal ABEntity GetEntityByAssetPath(string assetPath) internal ABEntity GetEntityByAssetPath(string assetPath)
{ {
@ -85,14 +108,20 @@ namespace VersionFlow.Runtime
return null; return null;
} }
internal void LoadAllBundle() Dictionary<string, GameObject> prefabSrcCache = new Dictionary<string, GameObject>();
{
foreach (var entity in m_entities) entity.LoadAB();
}
internal GameObject Instantiate(string assetPath, Transform parent = null) internal GameObject Instantiate(string assetPath, Transform parent = null)
{ {
var prefabSrc = LoadAsset<GameObject>(assetPath); if (assetPath.Contains("audiosourceclone"))
{
UnityEngine.Debug.Log("[123]");
}
if (!prefabSrcCache.TryGetValue(assetPath, out GameObject prefabSrc))
{
prefabSrc = LoadAsset<GameObject>(assetPath);
prefabSrcCache[assetPath] = prefabSrc;
}
if (prefabSrc == null) return null; if (prefabSrc == null) return null;
@ -111,11 +140,14 @@ namespace VersionFlow.Runtime
internal IEnumerator InstantiateAsync(string assetPath) internal IEnumerator InstantiateAsync(string assetPath)
{ {
var itor = LoadAssetAsync<GameObject>(assetPath); if (!prefabSrcCache.TryGetValue(assetPath, out GameObject prefabSrc))
{
while (itor.MoveNext()) yield return itor.Current; var itor = LoadAssetAsync<GameObject>(assetPath);
while (itor.MoveNext()) yield return itor.Current;
var prefabSrc = itor.Current as GameObject; prefabSrc = itor.Current as GameObject;
if (prefabSrc != null)
prefabSrcCache[assetPath] = prefabSrc;
}
if (prefabSrc == null) yield break; if (prefabSrc == null) yield break;
@ -220,11 +252,6 @@ namespace VersionFlow.Runtime
} }
} }
internal void UnLoadAsset(Object asset)
{
if (m_loadedAssets.TryGetValue(asset, out var ab) && ab != null) ab.UnLoadAsset(asset);
}
internal bool HasEntity(ABEntity ab) => m_entities.Contains(ab); internal bool HasEntity(ABEntity ab) => m_entities.Contains(ab);
internal bool TryDispose() internal bool TryDispose()
@ -234,7 +261,10 @@ namespace VersionFlow.Runtime
var hasPrefabInstance = CheckPrefabInstanceRef(out var needRemovePrefabSrcList); var hasPrefabInstance = CheckPrefabInstanceRef(out var needRemovePrefabSrcList);
foreach (var loadedPrefab in needRemovePrefabSrcList) //检测到可以Unload的Asset foreach (var loadedPrefab in needRemovePrefabSrcList) //检测到可以Unload的Asset
UnLoadAsset(loadedPrefab); {
var ab = VersionFlowX.BundleMgr.GetEntityByAsset(loadedPrefab);
ab.UnLoadAsset(loadedPrefab);
}
if (hasPrefabInstance) return false; if (hasPrefabInstance) return false;