Webgl page heap size increasing in each page load then crash

am getting aw snap or sometime not enough memory problem when I reload my webgl page. I have a webgl project which is empty (just a camera + light), developed in unity3d. I am reloading it, and profile its memory.

As you can see that its load 1.2MB in first load then 1281 MB in second then 1574 then 2160 and then get crash. I am amzed that why it is happening?

Another source of memory-related problems is the IndexedDB filesystem used by Unity. Any time you cache an asset bundle or use any filesystem-related methods, they are stored in a virtual filesystem backed by IndexedDB.

What you might not realize is that this virtual filesystem is loaded into and persisted in memory as soon as your Unity application starts. This means that if you are using the default Unity caching mechanism for Asset Bundles, you are adding the size of all of those bundles to the memory requirements for your game, even if they are not being loaded.

but the problem is i didn’t loaded anything from this build yet.

Even when i try to refresh my empty project several time in chrome i get this error:

For Mozilla there is an error log which states failed to asynchronoulsy prepare wasm: out of memory

1 Like

Is there a chance you could host a demo page somewhere? Given that memory usage persists across page reloads, it suggests something to do with IndexedDB, since that is the only mechanism that “remembers” state across page revisits.

If it is not IndexedDB, then it is a browser bug, since as far as web pages are concerned, when you navigate away from a page and come back, browsers should manage all unloading, and there is no mechanism how one could persist or leak memory for the browser after a web page closes. Hence if browsers are not buggy (given that it reproduces on multiple browsers suggests that they are not), then this points to something to do with IndexedDB. A reproducable test case would be much appreciated!

Thanks for your response, i have get stuck in this problem from last many days. I have comment different details
https://discussions.unity.com/t/596117/49
https://discussions.unity.com/t/694068/37
https://discussions.unity.com/t/729797/5
https://discussions.unity.com/t/683997/10

but found no attention by any unity staff, so thanks again you put some attention here.

Sorry i don’t have access to any server that i share with you while the second thing is that i am not quitting the tab of webgl i just reloading it through F5 or mouse click reload, then it increments the memory.

Some more details about the project:
Unity 2018.3.8
Enable Cached set to True
Testing on Chrome (73.0.3683.86)
Using Asset bundle

Here is the code snippet for loading asset bundle and destroying the object when don’t require:

 /// <summary>
    /// load assetbundle manifest, check hash, load actual bundle with hash parameter to use caching
    /// instantiate gameobject
    /// </summary>
    /// <param name="bundleURL">full url to assetbundle file</param>
    /// <param name="assetName">optional parameter to access specific asset from assetbundle</param>
    /// <returns></returns>
    IEnumerator DownloadAndCache(string bundleURL, string assetName = "")
    {
       
        //loadingImg.gameObject.SetActive(true);

        // get current bundle hash from server, random value added to avoid caching
        UnityWebRequest www;
            // now download the actual bundle, with hashString parameter it uses cached version if available
        //www = UnityWebRequest.GetAssetBundle(bundleURL + "?r=" + (Random.value * 9999999), hashString, 0);
        www = UnityWebRequestAssetBundle.GetAssetBundle(bundleURL);

        // wait for load to finish
        //yield return www.Send();
        yield return www.SendWebRequest();

        if (www.error != null)
        {
            Debug.LogError("www error: " + www.error);
            www.Dispose();
            www = null;
            yield break;
        }

        // get bundle from downloadhandler
        AssetBundle bundle = ((DownloadHandlerAssetBundle)www.downloadHandler).assetBundle;

        GameObject bundlePrefab = null;

        // if no asset name is given, take the first/main asset
        if (assetName == "")
        {
            bundlePrefab = (GameObject)bundle.LoadAsset(bundle.GetAllAssetNames()[0]);
        }
        else
        { // use asset name to access inside bundle
            bundlePrefab = (GameObject)bundle.LoadAsset(assetName);
        }

        // if we got something out
        if (bundlePrefab != null)
        {

            // instantiate at 0,0,0 and without rotation
            //nstantiate(bundlePrefab, Vector3.zero, Quaternion.identity);
            GameObject abObject = (GameObject)Instantiate(bundlePrefab, gameObject.transform.position, gameObject.transform.rotation);
            abObject.transform.parent = this.transform;
            if (AssetBundleLoadedAndInstantiated != null)
            {
                AssetBundleLoadedAndInstantiated(this.name);
            }
            //SetTreeShaderSettings(abObject);

            /*
            // fix pink shaders, NOTE: not always needed..
            foreach (Renderer r in go.GetComponentsInChildren<Renderer>(includeInactive: true))
            {
                // FIXME: creates multiple materials, not good
                var material = Shader.Find(r.material.shader.name);
                r.material.shader = null;
                r.material.shader = material;
            }*/
        }

        www.Dispose();
        www = null;

        // try to cleanup memory
        Resources.UnloadUnusedAssets();
        bundle.Unload(false);
        bundle = null;
        //loadingImg.gameObject.SetActive(false);
    }


    public void DestroyBundleObject()
    {
        if (this.gameObject.transform.childCount > 0)
        {
            Destroy(this.gameObject.transform.GetChild(0).gameObject);
            Resources.UnloadUnusedAssets();
        }
    }

I am using Kongregate WebGL utilities (WebGLCachedXMLHttpRequest) which is located in plugin folder(i guess it work automatically) as found that unity own classes are taking much more memory.

     var gameInstance = UnityLoader.instantiate("gameContainer", "%UNITY_WEBGL_BUILD_URL%", {onProgress: UnityProgress, Module: {
       //TOTAL_MEMORY: 268435456,
       // true in order to enable caching of the initially loaded .js, .data and .mem files   
     CachedXMLHttpRequestLoader : true,     
     //Set Module.CachedXMLHttpRequestSilent to true in order to disable cache logs in the console.
     CachedXMLHttpRequestSilent : true    ,
     //   Set Module.CachedXMLHttpRequestDisable to true in order to fully disable indexedDB caching.
     //CachedXMLHttpRequestDisable : true,
 
     }});

Remember other than this i have no important thing to share with you. On more thing is that i am not clear caching, and whenever user leave the tab i call this function.
Here is the javascript

function ViewerAppQuit(){
        if(gameInstance!=null)
        {
            gameInstance.SendMessage("GameFocusControl", "ViewerQuit");
            document.getElementById("gameContainer").outerHTML = "";
        }
    }

while the C# code is:

 public void ViewerQuit()
    {
        Debug.Log("Application Quit");
        Application.Quit();
    }

If you require more information i am available. Thanks

You can find a short video description here.
https://www.youtube.com/watch?v=EfYEkVdn2IQ

Just to bump this - I have the exact same issue as the original poster. Doing something similar aswel, loading a bunch of assetbundles from the server, cleaning them up and showing them. If I than press F5 I will get a increasingly high memory footprint eventually craching the browser.

The thing is, I am trying to update an old old build that was made in unity 2017 and I dont see the same problem there. That version is still running on the production machine and I can F5 all I want and the memory will never go over a the initial amount after loading is complete.

This to me sugests it has something to do with the changes from either removing the WWW class and using the webrequest or the changes in the unity build itself. My own code, the moments where I remove the unused objects and call assetbundle unload etc have not changed.

Will have to try some more things to see what makes this happen.

We have seen the exact same behaviour.

Thanks to unity (jukka_j), in another thread they provide the answer that memory increment when the browser Dev tools are open. So please check when dev tools are close, it will not increment the memory in chrome. While for firefox the behavior is same, no matter your dev tools are open or close, the memory is increment (seems it is firefox issue)

Please check this , jukka_j told that dev tools open is a problem and see my note above.

1 Like

This; if you have the cache disabled in the developer toolbar and press F5 it will not throw away the old cache (as one might expect) but just keep adding to the cache.

Not sure if this is all of the trouble.

1 Like

Not sure about cache, but you are stil testing with dev tools open. Don’t open the dev tools and just check the memory with chrome->settings->More Tools->Task Manager. Repeat your steps (loading page) and then check.