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; }
/// <summary> 此AB所在Chain </summary>
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)
{
@ -191,6 +192,7 @@ namespace VersionFlow.Runtime
if (!m_assetRefCount.ContainsKey(result))
{
m_assetRefCount[result] = 1;
s_AssetToABMapper[result] = this;
OnAssetLoad?.Invoke(this, result);
}
else m_assetRefCount[result]++;
@ -221,6 +223,7 @@ namespace VersionFlow.Runtime
if (!m_assetRefCount.ContainsKey(result))
{
m_assetRefCount[result] = 1;
s_AssetToABMapper[result] = this;
OnAssetLoad?.Invoke(this, result);
#if UNITY_EDITOR
@ -245,6 +248,8 @@ namespace VersionFlow.Runtime
{
m_assetRefCount.Remove(asset);
OnAssetUnLoad?.Invoke(this, asset);
s_AssetToABMapper.Remove(asset);
if (asset is not GameObject)
Resources.UnloadAsset(asset);

View File

@ -23,14 +23,14 @@ namespace VersionFlow.Runtime
/// <summary> shader变体收集器 </summary>
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);
/// <summary> 可选Bundle组:ABEntity </summary>
private readonly Dictionary<string, OptionalBundleDownloader> m_optionGroupDownloader = new Dictionary<string, OptionalBundleDownloader>();
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)
{
@ -90,23 +90,38 @@ namespace VersionFlow.Runtime
VersionFlowX.Log($"创建资源清单耗时:{sw.Elapsed.Milliseconds}ms");
}
internal BundleManager()
internal BundleManager()
{
VersionFlowX.BeginCoroutine(AutoReleaseCoroutine());
}
IEnumerator AutoReleaseCoroutine()
{
while (true)
{
if (VersionFlowX.Setting.AutoReleaseBundle && m_unloadDirty)
{
m_unloadDirty = false;
TryUnLoadBundles();
}
IEnumerator AutoReleaseCoroutine()
{
while (true)
{
if (VersionFlowX.Setting.AutoReleaseBundle && m_unloadDirty)
{
m_unloadDirty = false;
TryUnLoadBundles();
}
yield return null;
}
}
yield return null;
}
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)
@ -164,18 +179,10 @@ namespace VersionFlow.Runtime
internal LoadingChain GetLoadChain(ABEntity ab, bool shaderOnly)
{
LoadingChain targetChain = null;
foreach (var chain in m_loadingChains)
{
if (chain.m_topEntity == ab)
{
targetChain = chain;
break;
}
}
if (targetChain == null)
{
if (!m_loadingChains.TryGetValue(ab, out targetChain))
{
targetChain = LoadingChain.Create(ab, shaderOnly);
m_loadingChains.Add(targetChain);
m_loadingChains[ab] = targetChain;
}
return targetChain;
@ -203,7 +210,7 @@ namespace VersionFlow.Runtime
//找到已加载场景的loadchain
LoadingChain hasSceneChain = null;
foreach (var chain in m_loadingChains)
foreach (var chain in m_loadingChains.Values)
{
if (chain.m_currentLoadScenePath != null)
{
@ -238,7 +245,7 @@ namespace VersionFlow.Runtime
//找到已加载场景的loadchain
LoadingChain hasSceneChain = null;
foreach (var chain in m_loadingChains)
foreach (var chain in m_loadingChains.Values)
{
if (chain.m_currentLoadScenePath != null)
{
@ -378,18 +385,19 @@ namespace VersionFlow.Runtime
asset = null;
}
else
{
foreach (var chain in m_loadingChains)
{
chain.UnLoadAsset(asset);
}
{
var ab = GetEntityByAsset(asset);
if (ab != null)
{
ab.UnLoadAsset(asset);
}
asset = null;
if (!m_unloadDirty && VersionFlowX.Setting.AutoReleaseBundle)
{
m_unloadDirty = true;
}
if (!m_unloadDirty && VersionFlowX.Setting.AutoReleaseBundle)
{
m_unloadDirty = true;
}
}
}
public void ReleaseAsset<T>(IList<T> assetList) where T : UnityEngine.Object
@ -403,7 +411,7 @@ namespace VersionFlow.Runtime
assetList.Clear();
}
HashSet<LoadingChain> m_needRemoveChains = new HashSet<LoadingChain>();
HashSet<ABEntity> m_needRemoveChains = new HashSet<ABEntity>();
/// <summary>
/// 检查已加载的Bundle的引用计数为0并且没有任何依赖bundle被加载
/// 然后移除它
@ -417,13 +425,16 @@ namespace VersionFlow.Runtime
m_needRemoveChains.Clear();
foreach (var chain in m_loadingChains)
foreach (var item in m_loadingChains)
{
if (chain.TryDispose())
m_needRemoveChains.Add(chain);
}
var topAB = item.Key;
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>

View File

@ -50,8 +50,31 @@ namespace VersionFlow.Runtime
}
}
void Entity_OnAssetLoad(ABEntity sender, Object asset) => m_loadedAssets[asset] = sender;
void Entity_OnAssetUnLoad(ABEntity sender, Object asset) => m_loadedAssets.Remove(asset);
void Entity_OnAssetLoad(ABEntity sender, Object 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)
{
@ -85,14 +108,20 @@ namespace VersionFlow.Runtime
return null;
}
internal void LoadAllBundle()
{
foreach (var entity in m_entities) entity.LoadAB();
}
Dictionary<string, GameObject> prefabSrcCache = new Dictionary<string, GameObject>();
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;
@ -110,12 +139,15 @@ namespace VersionFlow.Runtime
}
internal IEnumerator InstantiateAsync(string assetPath)
{
var itor = LoadAssetAsync<GameObject>(assetPath);
while (itor.MoveNext()) yield return itor.Current;
var prefabSrc = itor.Current as GameObject;
{
if (!prefabSrcCache.TryGetValue(assetPath, out GameObject prefabSrc))
{
var itor = LoadAssetAsync<GameObject>(assetPath);
while (itor.MoveNext()) yield return itor.Current;
prefabSrc = itor.Current as GameObject;
if (prefabSrc != null)
prefabSrcCache[assetPath] = prefabSrc;
}
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 TryDispose()
@ -233,8 +260,11 @@ namespace VersionFlow.Runtime
var hasPrefabInstance = CheckPrefabInstanceRef(out var needRemovePrefabSrcList);
foreach (var loadedPrefab in needRemovePrefabSrcList) //检测到可以Unload的Asset
UnLoadAsset(loadedPrefab);
foreach (var loadedPrefab in needRemovePrefabSrcList) //检测到可以Unload的Asset
{
var ab = VersionFlowX.BundleMgr.GetEntityByAsset(loadedPrefab);
ab.UnLoadAsset(loadedPrefab);
}
if (hasPrefabInstance) return false;