Addressables: 14 seconds to load 100 text files, total size less than 0.5 megabytes, on a 9900K.

As the title says. This performance is ludicrously awful. What is going on here? I’m experimenting with Addressables to help with Switch load times; on my first title I used AssetBundles, which were pretty snappy. We got load times to less than 30 seconds for the entirety of all game data, which was several hundred megabytes.

With addressables, using LoadResourceLocationsAsync and then LoadAssetAsync, it is taking 14 seconds - yes, 14 - to load an addressable group with 100 TextAssets.

Things I have tried:

  • Switching from LZ4 to Uncompressed
  • Disabling CRC checks
  • Setting backgroundLoadingPriority to HIGH
  • Enabling Contiguous Bundles
  • Enabling “Use UnityWebRequest for Local”
  • Bundle Mode: Pack Separately OR Pack Together

Literally none of these things make any difference, or at best they slow the load time by 0.1 to 0.5 seconds.

LoadResourceLocationsAsync is extremely fast; the problematic and slow section is as follows:

        foreach (IResourceLocation location in handle.Result)
        {
            AsyncOperationHandle<TextAsset> textHandle = Addressables.LoadAssetAsync<TextAsset>(location);
            yield return textHandle;

            if (textHandle.Status == AsyncOperationStatus.Succeeded)
            {
                textAssets.Add(textHandle.Result);
                listOfMostRecentlyLoadedFileNames.Add(textHandle.DebugName);
            }
            if (textHandle.Status == AsyncOperationStatus.Failed)
            {
                TDebug.LogError(textHandle.DebugName + " did not load");
            }
            Addressables.Release(textHandle);
        }

I’m at a loss. This is many orders of magnitude slower than any other resource loading we’ve used. What are we doing wrong?

Some questions:

  • Is this in a player build or in the editor?
  • Is the group remote or local?
  • If remote, where are the assets hosted?
  • The code you pasted seems to load each file and then release it before moving to the next one. Was that intentional?

This is likely a issue with the way yielding is done, rather than the loading itself.
when you yield the textHandle, a minimum of one frame will occur before it continues.

instead you should start all the operations, then wait until all are done.

Something like this rough code.

List<AsyncOperationHandle<TextAsset>> handles = new xx;
foreach (IResourceLocation location in handle.Result)
{
    AsyncOperationHandle<TextAsset> textHandle = Addressables.LoadAssetAsync<TextAsset>(location);
    handles.Add(textHandle);
}
bool complete = false;
while (!complete)
{
   complete = true;
   foreach(var h in handles)
         if (h.isDone == false ){ complete = false; break }
    if (!complete)
        yield return null;
}
}

or better yet, start the handles, then do textHandle.Complete to register when it is complete, which can happen earlier.