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. Dismiss Notice

SetPixel/GetPixel causes memory leak?

Discussion in 'Scripting' started by KEMBL, May 27, 2011.

  1. KEMBL

    KEMBL

    Joined:
    Apr 16, 2009
    Posts:
    181
    Hello all! :)

    There is one problem, I know that they appear on this forum before :oops: , but old System.GC.Collect solutions seems not works on Unity 3.3 :( Lift My Eyelids!

    I am try to build our own GUI system, with component text formatting abilities like in RichEdit ( http://msdn.microsoft.com/en-us/library/bb787873 ). One of it is ability to write on several fonts/colors/scales/spaces in one textedit control.

    This task requires much of getPixel/setPixel operations, which growth the memory like a rocket (800 mb after 150-200 strings of the text).

    I was try to solve this problem with Garbage Collector, this not work as needs, in best chance they free 100mb and leave 700 for unknown reason. I do not use Threads or something similar "not classic" :)

    There is simple example of the code, which roads to described memory leak:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System;
    5.  
    6. public class TextureTest : MonoBehaviour {
    7.  public Texture2D texture;
    8.  int H = 100;
    9.  void Start()
    10.  {
    11.   texture = new Texture2D(0, 0, TextureFormat.RGBA32, false);
    12.  }
    13.  // Update is called once per frame
    14.  void Update ()
    15.  {
    16.      if (Input.GetKey(KeyCode.S))
    17.   {
    18.    texture.Resize(100, H, TextureFormat.RGBA32, false);
    19.    texture.SetPixels(new Color[100 * H]);
    20.    H += 100;
    21.    texture.Apply();
    22.   }  
    23.  }
    24. }
    25.  
    Please, take a look to this code, texture operations like getPixel/setPixel is one of the BASE game operations in Engine. If they not work fast and proper this really really really frustrating I think there is my bad, but do not see where. :(

    Thank! :)
     
    Last edited: May 27, 2011
  2. GisleAune

    GisleAune

    Joined:
    May 16, 2011
    Posts:
    88
    texture.SetPixels(new Color[100 * H]);
    H += 100;

    Does this variable reset?
     
    SparrowGS likes this.
  3. KEMBL

    KEMBL

    Joined:
    Apr 16, 2009
    Posts:
    181
    What does you mean?
    This variable grows by 100 and used for clear resized Texture2D texture. As texture is the same, they (how I understand) do not lose previous not resized copyes in memory. Also old array Color[100 * (H-1)] mast goes to GC, after reference to it replaced with new Color[100 * H].

    Today I try more simple example, I comment SetPixels string, memory will also grows, then I implement command

    Code (csharp):
    1.  
    2. texture.Resize(1, 1, TextureFormat.RGBA32, false);
    3.  
    by Keycode.D

    and memory was purged and stay free as when program starts, so the problem as i see in new Color which not moved by GC

    so, thre is workaround for such situations, it works without memleak:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System;
    5.  
    6. public class TextureTest : MonoBehaviour {
    7.  public Texture2D texture;
    8.  int H = 100;
    9.  Color[] color; // new global array for clean new textures
    10.  
    11.  void Start()
    12.  {
    13.   texture = new Texture2D(0, 0, TextureFormat.RGBA32, false);
    14.   color = new Color[100*100*10]; // init new array with some big num
    15.  }
    16.  
    17.  void Update ()
    18.  {
    19.      if (Input.GetKey(KeyCode.S))
    20.   {
    21.    texture.Resize(100, H, TextureFormat.RGBA32, false);
    22. //   texture.SetPixels(new Color[100 * H]);
    23.    texture.SetPixels(color); // this is replace, which not produce new Arrays
    24.    H += 100;
    25.    texture.Apply();
    26.   }
    27.   if (Input.GetKey(KeyCode.D))
    28.   {
    29.    texture.Resize(1, 1, TextureFormat.RGBA32, false);
    30.    H = 100;
    31.   }
    32.  }
    33. }
    34.  
    Take a look on Color[] color ( new global array for clean new textures ).
     
    Last edited: May 28, 2011
    GuruJeya14 likes this.
  4. Jonny-Roy

    Jonny-Roy

    Joined:
    May 29, 2013
    Posts:
    666
    Just for anyone coming across this in the future, this was causing me major issues, I had a bunch of 4096x4096 textures I was working on which was leaking. The long and short after trying everything, switch to GetPixels32 and SetPixels32, not only is it better memory wise (it's 4 bytes per color instead of 4 floats) but it also doesn't leak!
     
    josefgrunig likes this.
  5. exzizt

    exzizt

    Joined:
    Sep 30, 2017
    Posts:
    78
    I'm experiencing mad memory leaks with SetPixels as well. Will try out SetPixels32. Cheers!
     
    josefgrunig likes this.
  6. josefgrunig

    josefgrunig

    Joined:
    Jan 23, 2017
    Posts:
    56
    I am also experiencing huge memory leaks using GetPixels/SetPixels on Unity 2018.4.4f1 on iOS platform. Everything works when switching over to GetPixels32/SetPixels32, Thank You!
    Don't you have filed a bug report? Otherwise I will
     
  7. Tarrag

    Tarrag

    Joined:
    Nov 7, 2016
    Posts:
    215
    Had same prob with 2019.2 , get pixels32/setpixels32 really helped!
     
  8. GuruJeya14

    GuruJeya14

    Joined:
    Jun 29, 2017
    Posts:
    9
    Really thanks a lot!!! You saved me 1.2MB on frequent GC.Collect!!!
    I really understood the difference between
    pixels = camTexture.GetPixels32();
    and
    camTexture.GetPixels32(pixels);


    The prior creates new junk of memory slots (array) every time, while the latter uses the existing memory slots while just reassigning them.

    Thanks :)
     
  9. Lesnikus5

    Lesnikus5

    Joined:
    May 20, 2016
    Posts:
    131

    Could you explain where you found the GetPixel32 method that doesn't generate garbage? For me it generates garbage:

    Безымянный.jpg

    Have you used WebCamTexture.GetPixels32? There you can send your array to a method to avoid generating garbage. But how can the same be done with regular Texture2D? The Texture2D.GetPixels32 method creates an array inside itself, you cannot send your array to it to fill.
     
    Last edited: Feb 25, 2021
  10. Jonny-Roy

    Jonny-Roy

    Joined:
    May 29, 2013
    Posts:
    666
    Could you explain where you found the GetPixel32 method that doesn't generate garbage? For me it generates garbage:

    I was referring to memory leaking, not garbage.
     
  11. Blarp

    Blarp

    Joined:
    May 13, 2014
    Posts:
    267
    Still a problem in WebGL. VERY noticeable on Safari iPhone, will crash and not even work. Desktop WebGL is no problem.

    Note: using webgl 1.0 because safari is awful, not sure if that is a factor.