update asset bundle builder

优化资源包引用关系计算效率。
pull/72/head
hevinci 2023-02-27 18:11:51 +08:00
parent bcf6372602
commit 365ed560f6
17 changed files with 173 additions and 107 deletions

View File

@ -41,9 +41,9 @@ namespace YooAsset.Editor
// 是否显示LOG
if (buildParameters.BuildMode == EBuildMode.SimulateBuild)
BuildRunner.EnableLog = false;
BuildLogger.EnableLog = false;
else
BuildRunner.EnableLog = true;
BuildLogger.EnableLog = true;
// 创建构建节点
List<IBuildTask> pipeline;

View File

@ -138,7 +138,7 @@ namespace YooAsset.Editor
}
}
BuildRunner.Log($"发现未被依赖的资源并自动移除 : {dependAssetPath}");
BuildLogger.Log($"发现未被依赖的资源并自动移除 : {dependAssetPath}");
return true;
}
}

View File

@ -7,8 +7,6 @@ namespace YooAsset.Editor
{
public class BuildParametersContext : IContextObject
{
private readonly System.Diagnostics.Stopwatch _buildWatch = new System.Diagnostics.Stopwatch();
private string _pipelineOutputDirectory = string.Empty;
private string _packageOutputDirectory = string.Empty;
@ -117,22 +115,5 @@ namespace YooAsset.Editor
return buildParams;
}
/// <summary>
/// 获取构建的耗时(单位:秒)
/// </summary>
public float GetBuildingSeconds()
{
float seconds = _buildWatch.ElapsedMilliseconds / 1000f;
return seconds;
}
public void BeginWatch()
{
_buildWatch.Start();
}
public void StopWatch()
{
_buildWatch.Stop();
}
}
}

View File

@ -0,0 +1,30 @@

namespace YooAsset.Editor
{
public static class BuildLogger
{
/// <summary>
/// 是否启用LOG
/// </summary>
public static bool EnableLog = true;
/// <summary>
/// 日志输出
/// </summary>
public static void Log(string info)
{
if (EnableLog)
{
UnityEngine.Debug.Log(info);
}
}
/// <summary>
/// 日志输出
/// </summary>
public static void Info(string info)
{
UnityEngine.Debug.Log(info);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2bc82466a51f50141975e4424095aa09
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -2,13 +2,19 @@
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Diagnostics;
using UnityEngine;
namespace YooAsset.Editor
{
public class BuildRunner
{
public static bool EnableLog = true;
private static Stopwatch _buildWatch;
/// <summary>
/// 总耗时
/// </summary>
public static int TotalSeconds = 0;
/// <summary>
/// 执行构建流程
@ -23,14 +29,22 @@ namespace YooAsset.Editor
BuildResult buildResult = new BuildResult();
buildResult.Success = true;
TotalSeconds = 0;
for (int i = 0; i < pipeline.Count; i++)
{
IBuildTask task = pipeline[i];
try
{
_buildWatch = Stopwatch.StartNew();
var taskAttribute = task.GetType().GetCustomAttribute<TaskAttribute>();
Log($"---------------------------------------->{taskAttribute.Desc}<---------------------------------------");
BuildLogger.Log($"---------------------------------------->{taskAttribute.Desc}<---------------------------------------");
task.Run(context);
_buildWatch.Stop();
// 统计耗时
int seconds = GetBuildSeconds();
TotalSeconds += seconds;
BuildLogger.Log($"{taskAttribute.Desc}耗时:{seconds}秒");
}
catch (Exception e)
{
@ -42,26 +56,14 @@ namespace YooAsset.Editor
}
// 返回运行结果
BuildLogger.Log($"构建过程总计耗时:{TotalSeconds}秒");
return buildResult;
}
/// <summary>
/// 日志输出
/// </summary>
public static void Log(string info)
private static int GetBuildSeconds()
{
if (EnableLog)
{
UnityEngine.Debug.Log(info);
}
}
/// <summary>
/// 日志输出
/// </summary>
public static void Info(string info)
{
UnityEngine.Debug.Log(info);
float seconds = _buildWatch.ElapsedMilliseconds / 1000f;
return (int)seconds;
}
}
}

View File

@ -41,7 +41,7 @@ namespace YooAsset.Editor
throw new Exception("构建过程中发生严重错误!请查阅上下文日志!");
}
BuildRunner.Log("Unity引擎打包成功");
BuildLogger.Log("Unity引擎打包成功");
BuildResultContext buildResultContext = new BuildResultContext();
buildResultContext.UnityManifest = buildResults;
context.SetContextObject(buildResultContext);

View File

@ -40,7 +40,7 @@ namespace YooAsset.Editor
throw new Exception($"构建过程中发生错误 : {exitCode}");
}
BuildRunner.Log("Unity引擎打包成功");
BuildLogger.Log("Unity引擎打包成功");
BuildResultContext buildResultContext = new BuildResultContext();
buildResultContext.Results = buildResults;
context.SetContextObject(buildResultContext);

View File

@ -94,7 +94,7 @@ namespace YooAsset.Editor
// 刷新目录
AssetDatabase.Refresh();
BuildRunner.Log($"内置文件拷贝完成:{streamingAssetsDirectory}");
BuildLogger.Log($"内置文件拷贝完成:{streamingAssetsDirectory}");
}
}
}

View File

@ -67,7 +67,7 @@ namespace YooAsset.Editor
if (buildParameters.BuildMode != EBuildMode.SimulateBuild)
{
var buildResultContext = context.GetContextObject<TaskBuilding.BuildResultContext>();
UpdateBuiltinPipelineReference(patchManifest, buildResultContext, buildMapContext);
UpdateBuiltinPipelineReference(patchManifest, buildResultContext);
}
}
@ -76,7 +76,7 @@ namespace YooAsset.Editor
string fileName = YooAssetSettingsData.GetManifestJsonFileName(buildParameters.PackageName, buildParameters.PackageVersion);
string filePath = $"{packageOutputDirectory}/{fileName}";
PatchManifestTools.SerializeToJson(filePath, patchManifest);
BuildRunner.Log($"创建补丁清单文件:{filePath}");
BuildLogger.Log($"创建补丁清单文件:{filePath}");
}
// 创建补丁清单二进制文件
@ -86,7 +86,7 @@ namespace YooAsset.Editor
string filePath = $"{packageOutputDirectory}/{fileName}";
PatchManifestTools.SerializeToBinary(filePath, patchManifest);
packageHash = HashUtility.FileMD5(filePath);
BuildRunner.Log($"创建补丁清单文件:{filePath}");
BuildLogger.Log($"创建补丁清单文件:{filePath}");
PatchManifestContext patchManifestContext = new PatchManifestContext();
byte[] bytesData = FileUtility.ReadAllBytes(filePath);
@ -99,7 +99,7 @@ namespace YooAsset.Editor
string fileName = YooAssetSettingsData.GetPackageHashFileName(buildParameters.PackageName, buildParameters.PackageVersion);
string filePath = $"{packageOutputDirectory}/{fileName}";
FileUtility.CreateFile(filePath, packageHash);
BuildRunner.Log($"创建补丁清单哈希文件:{filePath}");
BuildLogger.Log($"创建补丁清单哈希文件:{filePath}");
}
// 创建补丁清单版本文件
@ -107,7 +107,7 @@ namespace YooAsset.Editor
string fileName = YooAssetSettingsData.GetPackageVersionFileName(buildParameters.PackageName);
string filePath = $"{packageOutputDirectory}/{fileName}";
FileUtility.CreateFile(filePath, buildParameters.PackageVersion);
BuildRunner.Log($"创建补丁清单版本文件:{filePath}");
BuildLogger.Log($"创建补丁清单版本文件:{filePath}");
}
}
@ -231,30 +231,96 @@ namespace YooAsset.Editor
return result;
}
/// <summary>
/// 更新资源包之间的引用关系
/// </summary>
#region 资源包引用关系相关
private readonly Dictionary<string, int> _cachedBundleID = new Dictionary<string, int>(10000);
private readonly Dictionary<string, string[]> _cachedBundleDepends = new Dictionary<string, string[]>(10000);
private void UpdateScriptPipelineReference(PatchManifest patchManifest, TaskBuilding_SBP.BuildResultContext buildResultContext)
{
int progressValue;
int totalCount = patchManifest.BundleList.Count;
// 缓存资源包ID
_cachedBundleID.Clear();
progressValue = 0;
foreach (var patchBundle in patchManifest.BundleList)
{
patchBundle.ReferenceIDs = GetScriptPipelineRefrenceIDs(patchManifest, patchBundle, buildResultContext);
int bundleID = GetAssetBundleID(patchBundle.BundleName, patchManifest);
_cachedBundleID.Add(patchBundle.BundleName, bundleID);
EditorTools.DisplayProgressBar("缓存资源包索引", ++progressValue, totalCount);
}
EditorTools.ClearProgressBar();
// 缓存资源包依赖
_cachedBundleDepends.Clear();
progressValue = 0;
foreach (var patchBundle in patchManifest.BundleList)
{
if (buildResultContext.Results.BundleInfos.ContainsKey(patchBundle.BundleName) == false)
throw new Exception($"Not found bundle in SBP build results : {patchBundle.BundleName}");
var depends = buildResultContext.Results.BundleInfos[patchBundle.BundleName].Dependencies;
_cachedBundleDepends.Add(patchBundle.BundleName, depends);
EditorTools.DisplayProgressBar("缓存资源包依赖列表", ++progressValue, totalCount);
}
private int[] GetScriptPipelineRefrenceIDs(PatchManifest patchManifest, PatchBundle patchBundle, TaskBuilding_SBP.BuildResultContext buildResultContext)
EditorTools.ClearProgressBar();
// 计算资源包引用列表
foreach (var patchBundle in patchManifest.BundleList)
{
if (buildResultContext.Results.BundleInfos.TryGetValue(patchBundle.BundleName, out var details) == false)
patchBundle.ReferenceIDs = GetBundleRefrenceIDs(patchManifest, patchBundle);
EditorTools.DisplayProgressBar("计算资源包引用关系", ++progressValue, totalCount);
}
EditorTools.ClearProgressBar();
}
private void UpdateBuiltinPipelineReference(PatchManifest patchManifest, TaskBuilding.BuildResultContext buildResultContext)
{
throw new Exception("Should never get here !");
int progressValue;
int totalCount = patchManifest.BundleList.Count;
// 缓存资源包ID
_cachedBundleID.Clear();
progressValue = 0;
foreach (var patchBundle in patchManifest.BundleList)
{
int bundleID = GetAssetBundleID(patchBundle.BundleName, patchManifest);
_cachedBundleID.Add(patchBundle.BundleName, bundleID);
EditorTools.DisplayProgressBar("缓存资源包索引", ++progressValue, totalCount);
}
EditorTools.ClearProgressBar();
// 缓存资源包依赖
_cachedBundleDepends.Clear();
progressValue = 0;
foreach (var patchBundle in patchManifest.BundleList)
{
var depends = buildResultContext.UnityManifest.GetDirectDependencies(patchBundle.BundleName);
_cachedBundleDepends.Add(patchBundle.BundleName, depends);
EditorTools.DisplayProgressBar("缓存资源包依赖列表", ++progressValue, totalCount);
}
EditorTools.ClearProgressBar();
// 计算资源包引用列表
progressValue = 0;
foreach (var patchBundle in patchManifest.BundleList)
{
patchBundle.ReferenceIDs = GetBundleRefrenceIDs(patchManifest, patchBundle);
EditorTools.DisplayProgressBar("计算资源包引用关系", ++progressValue, totalCount);
}
EditorTools.ClearProgressBar();
}
List<string> referenceList = new List<string>();
foreach (var keyValuePair in buildResultContext.Results.BundleInfos)
private int[] GetBundleRefrenceIDs(PatchManifest patchManifest, PatchBundle targetBundle)
{
string bundleName = keyValuePair.Key;
if (bundleName == patchBundle.BundleName)
List<string> referenceList = new List<string>();
foreach (var patchBundle in patchManifest.BundleList)
{
string bundleName = patchBundle.BundleName;
if (bundleName == targetBundle.BundleName)
continue;
if (keyValuePair.Value.Dependencies.Contains(patchBundle.BundleName))
string[] dependencies = GetCachedBundleDepends(bundleName);
if (dependencies.Contains(targetBundle.BundleName))
{
referenceList.Add(bundleName);
}
@ -263,46 +329,28 @@ namespace YooAsset.Editor
List<int> result = new List<int>();
foreach (var bundleName in referenceList)
{
int bundleID = GetAssetBundleID(bundleName, patchManifest);
int bundleID = GetCachedBundleID(bundleName);
if (result.Contains(bundleID) == false)
result.Add(bundleID);
}
return result.ToArray();
}
/// <summary>
/// 更新资源包之间的引用关系
/// </summary>
private void UpdateBuiltinPipelineReference(PatchManifest patchManifest, TaskBuilding.BuildResultContext buildResultContext, BuildMapContext buildMapContext)
private int GetCachedBundleID(string bundleName)
{
foreach (var patchBundle in patchManifest.BundleList)
if (_cachedBundleID.TryGetValue(bundleName, out int value) == false)
{
patchBundle.ReferenceIDs = GetBuiltinPipelineRefrenceIDs(patchManifest, patchBundle, buildResultContext, buildMapContext);
throw new Exception($"Not found cached bundle ID : {bundleName}");
}
return value;
}
private int[] GetBuiltinPipelineRefrenceIDs(PatchManifest patchManifest, PatchBundle patchBundle, TaskBuilding.BuildResultContext buildResultContext, BuildMapContext buildMapContext)
private string[] GetCachedBundleDepends(string bundleName)
{
List<string> referenceList = new List<string>();
foreach (var bundleInfo in buildMapContext.BundleInfos)
if (_cachedBundleDepends.TryGetValue(bundleName, out string[] value) == false)
{
string bundleName = bundleInfo.BundleName;
if (bundleName == patchBundle.BundleName)
continue;
string[] dependencies = buildResultContext.UnityManifest.GetDirectDependencies(bundleName);
if (dependencies.Contains(patchBundle.BundleName))
{
referenceList.Add(bundleName);
throw new Exception($"Not found cached bundle depends : {bundleName}");
}
return value;
}
List<int> result = new List<int>();
foreach (var bundleName in referenceList)
{
int bundleID = GetAssetBundleID(bundleName, patchManifest);
if (result.Contains(bundleID) == false)
result.Add(bundleID);
}
return result.ToArray();
}
#endregion
}
}

View File

@ -25,7 +25,7 @@ namespace YooAsset.Editor
var buildParameters = buildParametersContext.Parameters;
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
BuildRunner.Log($"开始拷贝补丁文件到补丁包目录:{packageOutputDirectory}");
BuildLogger.Log($"开始拷贝补丁文件到补丁包目录:{packageOutputDirectory}");
if (buildParameters.BuildPipeline == EBuildPipeline.ScriptableBuildPipeline)
{

View File

@ -13,16 +13,12 @@ namespace YooAsset.Editor
var buildParameters = context.GetContextObject<BuildParametersContext>();
var buildMapContext = context.GetContextObject<BuildMapContext>();
var patchManifestContext = context.GetContextObject<PatchManifestContext>();
buildParameters.StopWatch();
var buildMode = buildParameters.Parameters.BuildMode;
if (buildMode != EBuildMode.SimulateBuild)
{
CreateReportFile(buildParameters, buildMapContext, patchManifestContext);
}
float buildSeconds = buildParameters.GetBuildingSeconds();
BuildRunner.Info($"Build time consuming {buildSeconds} seconds.");
}
private void CreateReportFile(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext, PatchManifestContext patchManifestContext)
@ -42,7 +38,7 @@ namespace YooAsset.Editor
#endif
buildReport.Summary.UnityVersion = UnityEngine.Application.unityVersion;
buildReport.Summary.BuildDate = DateTime.Now.ToString();
buildReport.Summary.BuildSeconds = (int)buildParametersContext.GetBuildingSeconds();
buildReport.Summary.BuildSeconds = BuildRunner.TotalSeconds;
buildReport.Summary.BuildTarget = buildParameters.BuildTarget;
buildReport.Summary.BuildPipeline = buildParameters.BuildPipeline;
buildReport.Summary.BuildMode = buildParameters.BuildMode;
@ -107,7 +103,7 @@ namespace YooAsset.Editor
string fileName = YooAssetSettingsData.GetReportFileName(buildParameters.PackageName, buildParameters.PackageVersion);
string filePath = $"{packageOutputDirectory}/{fileName}";
BuildReport.Serialize(filePath, buildReport);
BuildRunner.Log($"资源构建报告文件创建完成:{filePath}");
BuildLogger.Log($"资源构建报告文件创建完成:{filePath}");
}
/// <summary>

View File

@ -56,7 +56,7 @@ namespace YooAsset.Editor
FileUtility.CreateFile(filePath, encryptResult.EncryptedData);
bundleInfo.EncryptedFilePath = filePath;
bundleInfo.LoadMethod = encryptResult.LoadMethod;
BuildRunner.Log($"Bundle文件加密完成{filePath}");
BuildLogger.Log($"Bundle文件加密完成{filePath}");
}
// 进度条

View File

@ -15,7 +15,7 @@ namespace YooAsset.Editor
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
var buildMapContext = BuildMapCreater.CreateBuildMap(buildParametersContext.Parameters.BuildMode, buildParametersContext.Parameters.PackageName);
context.SetContextObject(buildMapContext);
BuildRunner.Log("构建内容准备完毕!");
BuildLogger.Log("构建内容准备完毕!");
// 检测构建结果
CheckBuildMapContent(buildMapContext);

View File

@ -12,8 +12,6 @@ namespace YooAsset.Editor
void IBuildTask.Run(BuildContext context)
{
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
buildParametersContext.BeginWatch();
var buildParameters = buildParametersContext.Parameters;
// 检测构建参数合法性
@ -57,7 +55,7 @@ namespace YooAsset.Editor
string platformDirectory = $"{buildParameters.OutputRoot}/{buildParameters.PackageName}/{buildParameters.BuildTarget}";
if (EditorTools.DeleteDirectory(platformDirectory))
{
BuildRunner.Log($"删除平台总目录:{platformDirectory}");
BuildLogger.Log($"删除平台总目录:{platformDirectory}");
}
}
@ -65,7 +63,7 @@ namespace YooAsset.Editor
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
if (EditorTools.CreateDirectory(pipelineOutputDirectory))
{
BuildRunner.Log($"创建输出目录:{pipelineOutputDirectory}");
BuildLogger.Log($"创建输出目录:{pipelineOutputDirectory}");
}
}
}

View File

@ -101,7 +101,7 @@ namespace YooAsset.Editor
}
*/
BuildRunner.Log("构建结果验证成功!");
BuildLogger.Log("构建结果验证成功!");
}
/// <summary>

View File

@ -62,7 +62,7 @@ namespace YooAsset.Editor
throw new System.Exception("存在差异资源包!请查看警告信息!");
}
BuildRunner.Log("构建结果验证成功!");
BuildLogger.Log("构建结果验证成功!");
}
}
}