Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Loading 500 Textures with UnityWebRequest In WebGL is Throwing Memory Allocation Error.

Discussion in 'WebGL' started by yusuf_isik, Feb 25, 2021.

  1. yusuf_isik

    yusuf_isik

    Joined:
    Feb 14, 2014
    Posts:
    21
    Hello. I'm developing an exhibition app with Unity WebGL. I've decided to load Images with UWP(UnityWebRequest) to reduce my first loading time. Because my base app is 70MB. All images are smaller than 2048x2048px in real size. And file sizes are 300-500kb. The average total size of the pictures is ~200MB. Everything is looking reasonable according to today's internet speed. But somehow, my internet browser(Opera) gives an Memory Allocation Error when loading my images in to Unity WebGL app. It says that error:

    WebGL.framework.js:3338 Could not allocate memory: System out of memory!
    Trying to allocate: 5805543B with 16 alignment. MemoryLabel: Texture
    Allocation happened at: Line:70 in ./Runtime/Utilities/dynamic_array.h
    Memory overview

    [ ALLOC_TEMP_THREAD ] used: 32768B | peak: 0B | reserved: 4194304B
    [ ALLOC_TEMP_JOB_1_FRAME ] used: 0B | peak: 0B | reserved: 262144B
    [ ALLOC_TEMP_JOB_2_FRAMES ] used: 0B | peak: 0B | reserved: 262144B
    [ ALLOC_TEMP_JOB_4_FRAMES ] used: 0B | peak: 0B | reserved: 1048576B
    [ ALLOC_TEMP_JOB_ASYNC ] used: 15440582B | peak: 0B | reserved: 17039360B
    [ ALLOC_DEFAULT ] used: 50305651B | peak: 57639027B | reserved: 51652762B
    [ ALLOC_GAMEOBJECT ] used: 393738B | peak: 926820B | reserved: 419199B
    [ ALLOC_GFX ] used: 2014771894B | peak: 2014771894B | reserved: 2014809667B
    [ ALLOC_PROFILER ] used: 866833B | peak: 4453539B | reserved: 970108B


    I'm not getting what is the problem. This numbers are huge according to my 200mb(204800B) images. Here is my script:
    Code (CSharp):
    1. public IEnumerator GetImage(string mainURL, string imageFileName, System.Action<Texture2D> callback = null)
    2.     {
    3.         //print(url + imageFileName);
    4.         using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(mainURL + imageFileName))
    5.         {
    6.             yield return uwr.SendWebRequest();
    7.  
    8.             if (uwr.result == UnityWebRequest.Result.ConnectionError || uwr.result == UnityWebRequest.Result.ProtocolError || uwr.result == UnityWebRequest.Result.DataProcessingError)
    9.             {
    10.                 Debug.Log(uwr.error + "\n" + imageFileName + " is missing!");
    11.                 yield return null;
    12.             }
    13.             else
    14.             {
    15.                 Texture2D texture = DownloadHandlerTexture.GetContent(uwr);
    16.                 callback?.Invoke(texture);
    17.                 uwr.Dispose();
    18.                 yield return null;
    19.  
    20.             }
    21.             yield return null;
    22.         }
    23.        
    24.         yield return null;
    25.     }
    Is anyone can explain to me what is the problem. Am I facing some kind of technical limit or doing something wrong?
     
  2. sumpfkraut

    sumpfkraut

    Joined:
    Jan 18, 2013
    Posts:
    241
    They require a multiple of 500kb because they are not loaded in compressed form.
    And you can not clean up memory without closing the tab. (afaik)

    you can try with 512x512 images, but i think it's still to much.
    or try with less images and see how many memory is used.

    here is a MemoryStatsPlugin (jslib) pearhaps this helps https://blogs.unity3d.com/kr/2016/12/05/unity-webgl-memory-the-unity-heap/

    I also use image-uploads for users, and the only way i found was to resize all textures above 512px textures.
    And hope that there is enough memory aviable until they close the browser.
     
    yusuf_isik likes this.
  3. yusuf_isik

    yusuf_isik

    Joined:
    Feb 14, 2014
    Posts:
    21
    I've tried again to load 500 images. And I've watched the windows task manager about ram usage of opera. I've saw that it's given error after passing 2gb of ram usage. After that I've tried to load 300 images. It's completed without error. Ram usage got close to 2gb limit, but it's not passed that limit. Everything's expected until that point. But I've noticed a new thing. Ram usage of opera's dropped to 400mb from 1.8gb after the texture downloading and assigning operation. With that observation, I can confirm that garbage collection is cleaning somethings.

    I'm starting GetImage routines in a "for loop" for my all different object. I think, it isn't clean the loop until finishing to load every texture. My loop function:
    Code (CSharp):
    1. public void DownloadLayouts(Hodja[] hodjas, string mainURL)
    2. {
    3.        for (int i = 0; i < hodjas.Length; i++)
    4.         {
    5.             for (int j = 0; j < hodjas[i].finalDocuments.Length; j++)
    6.             {
    7.                 string imageFileName = "blablabla.jpg";
    8.  
    9.                 int si = i;
    10.                 int sj = j;
    11.                 StartCoroutine(GetImage(mainURL, imageFileName, (sImage) =>
    12.                 {
    13.                     hodjas[si].finalDocuments[sj] = sImage;
    14.                 }));
    15.             }
    16.         }
    17. }
    I don't know how to make this Garbage Collection friendly. Any opinion?
     
    scott31 likes this.
  4. De-Panther

    De-Panther

    Joined:
    Dec 27, 2009
    Posts:
    553
    tjumma and yusuf_isik like this.
  5. yusuf_isik

    yusuf_isik

    Joined:
    Feb 14, 2014
    Posts:
    21
    De-Panther likes this.
  6. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    944
    Good to note here is that WebAssembly has a 2GB memory usage limit. Planned for Unity 2021.2, this should be possible to be bumped up to 4GB, but currently only Chromium based browsers will support that 4GB limit.