Search Unity

Does Unity Cache Results of Resources.Load?

Discussion in 'Scripting' started by topsekret, Sep 26, 2014.

  1. topsekret

    topsekret

    Joined:
    Apr 18, 2013
    Posts:
    69
    Simple question. Obviously, the first time you call Resources.Load for a given asset, it will be a little slow since it has to load from disc. However, if you were to call Resources.Load on the same asset again, would it be able to return the reference to you from a cache instead of loading from disc (provided that the asset was not unloaded between calls)?

    Code (CSharp):
    1. Material mat = (Material)Resources.Load("MyMat", typeof(Material));  //has to load from disc
    2. Material mat2 = (Material)Resources.Load("MyMat", typeof(Material)); //will this be the same speed as the previous call or faster because Unity caches?
    Obviously, I could write my own caching code, but I would like to not reinvent the wheel if Resources.Load does this for us.
     
  2. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    Someone please correct me if I'm wrong, especially the VRAM thing. I haven't tested this stuff since my last released game about a year ago.

    Textures that go in VRAM need to be unloaded either by using Resources.UnloadAsset(), Resources.UnloadUnusedAssets() or a scene change.

    Everything else follows normal garbage collection rules. If an object exists without any references to it, the object will be deleted next time garbage is collected.
     
  3. topsekret

    topsekret

    Joined:
    Apr 18, 2013
    Posts:
    69
    So that's a yes, then? In my sample code, the call to Resource.Load at line 2 will be faster than the call at line 1 since the asset in question is already in memory?
     
  4. Venryx

    Venryx

    Joined:
    Sep 25, 2012
    Posts:
    444
    I did a test with calling Resources.Load on a texture 1000 times, and then 1000 times simply retrieving the value from a Dictionary cache, and the Resources.Load took about 3 times as long. So, it's not that much slower, but if you need full performance, adding your own layer of cache can help.

    Test Code:
    Code (CSharp):
    1.         // call each one once, to make sure any internal cache is able to be populated
    2.         Resources.Load<Texture2D>("Soils/Grass");
    3.         VResources.Load<Texture2D>("Soils/Grass");
    4.  
    5.         VDebug.StartTime(); // (custom debug class that just measures the time between StartTime and MarkTime)
    6.         for (int i = 0; i < 1000; i++)
    7.             Resources.Load<Texture2D>("Soils/Grass");
    8.         VDebug.MarkTime("NoCache) ");
    9.         VDebug.StartTime();
    10.         for (int i = 0; i < 1000; i++)
    11.             VResources.Load<Texture2D>("Soils/Grass");
    12.         VDebug.MarkTime("Cache) ");
    VResources Class)
    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3.  
    4. public static class VResources
    5. {
    6.     static Dictionary<string, Object> resourceCache = new Dictionary<string, Object>();
    7.     public static T Load<T>(string path) where T : Object
    8.     {
    9.         if (!resourceCache.ContainsKey(path))
    10.             resourceCache[path] = Resources.Load<T>(path);
    11.         return (T)resourceCache[path];
    12.     }
    13. }
    Test Results (did them more than once, and they came out about the same each time):
    NoCache) 4.3648
    Cache) 1.6073