Hello,
I am developing a Gear VR application that must download a number of large video files. I’m finding that after downloading roughly six or more ~100 MB files, the app behaves as if it is running out of memory-- failing to load assets or crashing on scene loads. If the app is rebooted, it does not download the files again (as it finds them in persistentDataPath) and behaves as expected. I have restructured the code several times, either utilizing using() blocks, manually calling www.Dispose(), and aggressively calling System.GC.Collect(), but none of that had any effect on the behaviour.
It’s worth noting that this problem only occurs on the Note 4. S6s are able to proceed without issue, I’m presuming because they have enough spare memory to operate correctly even with the leak. It’s also possible that WWW is not at fault and something else (maybe System.IO.Filestream) is the root of the problem.
Also of note: the same problem was observed in a previous version of the app that used WWW to transfer the files out of StreamingAssets via a jar:// URI, rather than fetching the files from an external server.
I’m using Unity 5.2.2.p4. I’ve found mentions of a WWW memory leak on iOS, but that was presumably patched several versions ago, and is an entirely different platform in any case.
Code follows, trimmed for clarity:
private void Start()
{
StartCoroutine(AllDownloads());
}
private IEnumerator AllDownloads()
{
foreach (VideoInfo video in mVideos)
{
yield return StartCoroutine(Download(video));
}
}
private IEnumerator Download(VideoInfo video)
{
string writePath = Application.persistentDataPath + "/" + video.Name;
WWW www = new WWW(Host + video.Name);
while (!www.isDone)
{
yield return new WaitForSeconds(0.1f);
}
if (!string.IsNullOrEmpty(www.error))
{
//Error Handling Code -- snipped - Loads a different scene, destroying this object.
yield break;
}
System.IO.FileStream file = System.IO.File.Create(writePath);
int written = 0;
byte[] bytes = www.bytes;
while (written < www.bytesDownloaded)
{
try
{
file.Write(bytes, written, Mathf.Min(CHUNK_SIZE, www.bytesDownloaded - written));
}
catch(Exception)
{
//Error Handling Code -- snipped - Loads a different scene, destroying this object.
yield break;
}
written += CHUNK_SIZE;
yield return null;
}
www.Dispose();
www = null;
file.Close();
file.Dispose();
file = null;
bytes = null;
}
}