Creating a MemoryStream from WWW.bytes leaks memory

I’m currently using Unity 4.5.5f1 and creating an iOS application using XCode 6.1.1

I’ve externalized many assets n 4 different zip files. I download them using the WWW class. I unzip and save the assets to the disk and all is cool with that. However, testers came back with the app crashing on lower memory devices (iPad Mini, iPad2) on first play through after the downloading completed. Additional note: This coroutine is contained in a monobehaviour class that is added as a component prior to use and destroyed after it is done being used.

I have broken down my code to the problem, but I don’t know the solution. The problem arises when I create a MemoryStream using the bytes from the WWW class. I have a simple coroutine that downloads the zip file, creates the memory stream, unzips/writes/saves files, and then finishes. I have the coroutine down to 2 elements now (download the zip, create the memory stream).

public IEnumerator DownloadAndProcessZip(string path, string pathToSaveFilesTo)
	{
		percentComplete = 0.0f;

		using(WWW www = new WWW(path))
		{
			while(!www.isDone)
			{
				percentComplete = www.progress * 0.5f;
				yield return 0;
			}

			//create the memory stream with the www.bytes
			//using(MemoryStream zipFileStream = new MemoryStream(www.bytes))
			{
				//after it is downloaded
				//I'm doing nothing for now
			}

			yield return 0;
		}
		System.GC.Collect();
		System.GC.WaitForPendingFinalizers();
		percentComplete = 1.0f;
	}

As you can see, I have the MemoryStream creation commented out. This results in the following memory usage:
[38378-screen+shot+2015-01-07+at+11.19.39+am.png|38378]

As you can see the 4 spikes in memory are the downloading of the zips and then the memory gets dumped and all is well. The last spike is immediately followed by background level loading so the memory doesn’t get back down to the 30mb I started with prior to downloading.

Once I un-comment the MemoryStream creation:

 public IEnumerator DownloadAndProcessZip(string path, string pathToSaveFilesTo)
    	{
    		percentComplete = 0.0f;
    
    		using(WWW www = new WWW(path))
    		{
    			while(!www.isDone)
    			{
    				percentComplete = www.progress * 0.5f;
    				yield return 0;
    			}
    
    			//create the memory stream with the www.bytes
    			using(MemoryStream zipFileStream = new MemoryStream(www.bytes))
    			{
    				//after it is downloaded
    				//I'm doing nothing for now
    			}
    
    			yield return 0;
    		}
    		System.GC.Collect();
    		System.GC.WaitForPendingFinalizers();
    		percentComplete = 1.0f;
    	}

I get this memory usage:
[38379-screen+shot+2015-01-07+at+11.31.34+am.png|38379]

The drop furthest to the right is when the last file has finished downloading. As you can see from the code I am using using and my IDisposable objects should be cleaned up/disposed of properly once they fall out of scope. This is a huge problem. I’m starting in the hole by roughly 120-150mb stuck in memory and when you only get about 250ish on the low memory devices to play with before you have problems, that is a huge issue.

I saw that the WWW class for iOS had a memory leak prior to 4.5 and I found the code and indeed the _data is being released once and I found the retain for the NSMutableData so that should be good. Is it possible it is getting retained elsewhere in Obj-C that it needs to be released with? I’m running out of ideas here and this is a major issue.

Thank you in advance for any help.

Edit 1 and Possible Work Around
So I have a thought as to why this is occurring. By accessing the content (in this case bytes) of the WWW, they have to be passed from the Obj-C native side to the scripting side. How this occurs, I have no clue as the code is hidden from me. If it is like writing an iOS plug in that returns a char *, you have to allocate a new char * and pass it over. I have a feeling that this copy is being held onto in memory, or the reference count of the NSMutableData array is being retained but never subsequently released and when the clean up occurs, it releases and nils the _data, effectively losing the reference and then that memory is leaked.

I found a downloading alternative here: Top Answer I fiddled with the code some and now I can download the files directly to disk and the memory never spikes. I can’t attach any more pictures unfortunately, but the memory sits @ roughly 32mbs for the entire download process.

I’m not sure if this is the best or most right solution to this problem, but it does work. I would suspect a properly working WWW class in Unity would be the preferred way of handling this. So if anyone has any other solutions, I’m all ears. Thanks again

Something that’s sticking out to me is that you’re not calling zipFileStream.Close() before you dispose of everything.