-
Notifications
You must be signed in to change notification settings - Fork 102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Performance issue of AssetsTools.NET #86
Comments
Can you check which asset types in particular take a long time to load? I bet this is probably types with byte arrays which are typed like regular arrays being read as regular arrays which makes each element in a byte array an entire object with properties. One of the more common examples are shaders iirc. |
Font is extremely slow - exclude 20 Fonts reduces total wall time by 40%. |
The Font asset does indeed use a regular Array instead of a TypelessData one. You can modify the template to read it as a byte array instead of a normal array if you want. (Note: I wrote this for the at3 branch. for at2, you'll need to change MakeValue to the AssetTypeInstance constructor.) using AssetsTools.NET;
using AssetsTools.NET.Extra;
static AssetTypeValueField? GetByteArrayFont(AssetsManager am, AssetsFileInstance inst, AssetFileInfo inf)
{
AssetTypeTemplateField fontTemp = am.GetTemplateBaseField(inst, inf);
AssetTypeTemplateField? m_FontData = fontTemp.Children.FirstOrDefault(f => f.Name == "m_FontData");
if (m_FontData == null)
return null;
AssetTypeTemplateField m_FontData_Array = m_FontData.Children[0];
m_FontData_Array.ValueType = AssetValueType.ByteArray;
m_FontData_Array.Type = "TypelessData";
AssetTypeValueField baseField = fontTemp.MakeValue(inst.file.Reader, inf.AbsoluteByteStart);
return baseField;
}
void Load()
{
var assetsManager = new AssetsManager();
assetsManager.LoadClassPackage("classdata.tpk");
var afileInst = assetsManager.LoadAssetsFile(args[0], false);
var afile = afileInst.file;
assetsManager.LoadClassDatabaseFromPackage(afile.Metadata.UnityVersion);
foreach (var assetInfo in afile.GetAssetsOfType(AssetClassID.Font))
{
var dummy = GetByteArrayFont(assetsManager, afileInst, assetInfo);
Console.WriteLine($"data size: {dummy["m_FontData.Array"].AsByteArray.Length} bytes");
}
}
if (args.Length < 1)
{
Console.WriteLine("need a file argument");
return;
}
Load(); |
I tried to make a (assets-only) PoC to support thread-safe reading. |
Maybe I can look at it later, but right now I'm still trying to fix up the at3 branch to be mostly bug free before I move onto any newer features like this. However, the bulk of the wait time isn't reading from disk but deserialization, so if I were doing this, I wouldn't touch the binary readers (plus that just adds more complexity). |
Reader is the major (or only, if I was correct) thing that prevents thread-safe reading and deserialization. |
What I meant was you could read a bunch of assets into individual memory streams/binary readers and not worry about sharing the same stream/reader. The only thing that would have to be single threaded would be disk->memory stream but that would be it. |
А зачем вы объявляете переменную "var dummy" внутри массива? |
Very slow compressing/decomressing bundle files, especially lzma ones. On CPU i7-8700 usage is below 10%. 1Gb bundle takes about 5 min to compress or decompress and don't matter if I'm doing it in UABEA or using manually written tool based on AssetsTools.NET.dll. |
@suphamster LZMA decompression/compression uses the official 7z sdk, and unfortunately unless we swap it out with the native version or rewrite it, it'll always be that slow. I don't really know of any other managed c# library that could get the job done. |
It seems there are no fast C# LZMA implementation https://stackoverflow.com/questions/12292593/why-is-lzma-sdk-7-zip-so-slow |
Easy Compressor uses the same exact library for LZMA and the same library for LZ4, although the version I'm using for LZ4 is a bit old in order to support .NET 3.5. I'm sure the LZ4 stuff could be upgraded if you wanted more speed, but LZMA is the really slow one. |
I practiced a AssetsTools.NET helloworld by dumping an assets list, but found it slower than expectation.
A minimal loop like this could end up in pretty bad performance.
Some performance numbers:
(Linux/Mono 5.15.0/6.12; i7-8809G/kabylake 3.1-4.2G)
(Resources size: around 4GiB, 64k assets)
According to mono profiler:
(Use mode=throughput is about 5-10% faster and situation does not really change)
Is it possible to reduce objects count? (I guess most of them will be persistent?)
With so many objects, proceeding GC could also be slow.
The text was updated successfully, but these errors were encountered: