Anderberg

Audio + memory usage = headache

11 posts in this topic

Does anyone know how to unload and destroy audio files appropriately?

I have about 12 MB of audio in my game, or about 15 minutes. I do not load all of them at one time, since this will break any mobile browser. So I load them in the states they are needed. About 4 MB is loaded at the same time.

 

According to the Task Manager in chrome, the memory used by my game just keeps growing and growing, easily above 1000MB by changing states. (Browsers decode audio to lossless => memory use is high, regardless of file format and encoding.)

 

In all states I have a shutdown function that destroys all the sounds and purges audio loaded in the cache. This is my current code (very similar to how cache is cleared when changing states, but I have some assets I use everywhere and don't want to remove):

function clearCache () {  // Purge sound.  var key = this.sound._sounds.length;  while (key--) {    this.sound._sounds[key].destroy(true);  }  // Destroy "everything" in cache.  for (var i = 0; i < this.cache._cacheMap.length; i++) {    var cache = this.cache._cacheMap[i];    for (key in cache) {      if (key !== '__default' && key !== '__missing' && this.cache._doNotDelete.indexOf(key) < 0) {        if (cache[key].destroy) {          cache[key].destroy();        }      delete cache[key];      }    }  }}

(Note: This problem did not occur in previous Phaser versions, so I am suspecting that some reference to the audio files are lingering, but can't find out where.)

 

Also, if anyone has a good way of profiling and debugging browser audio, please share, I haven't found a good way to figure out where all this memory goes (Chrome heap profiler says that I use | 20MB).

Share this post


Link to post
Share on other sites

Sounds very familiar. In our project that had three tracks for menus and one+sound effects for the actual game, memory usage rocketed to 1200mb in menus and in game it dropped to 700-800mb. Then when returning from game to menu, garbace collector wasn't fast enough to clear memory although cache was indeed cleared. This caused game to use something like 700mb+1200mb of memory effectively crashing any browser. In chrome it just trew oh snap and on firefox caused decoding error. Other issues with web audio were very long loading times, random decoding errors, horrible performance, memory leaks and so on. Like with you, cache was cleared between states, both maually and with state.start(X,true,true).
I'm sorry that I can't really help you with this as in the end we scraped both web audio and phaser sound system and switched to use vanilla JS new Audio() method. This actually removed whole bunch of issues in the project, including abyssal memory usage.

 

EDIT: there is also option in Phaser sound manager to use audio tag which might fix some of your issues. I haven't personally tested it but I sort of guess that it still uses same methods and properties as with web audio and therefore saving the effort of rewriting your code f you wan't to try it out.

Share this post


Link to post
Share on other sites

RedPanduzer: Even though you didn't find a solution for web audio it is somehow good to hear that I am not the only one with this problem :)

My memory usage should peak at about 400-500MB (using web audio) and go back down to 250-300. At least that is what happened in earlier Phaser versions.

 

Thanks for the tip about not using web audio. I will experiment a bit to see if it will fix it for me! I've read up before that audio tags can only play one at the time, but perhaps that has changed, I'll try it out none the less.

Share this post


Link to post
Share on other sites

I still haven't found a solution for this problem, so I created an isolated test case and hope that someone can confirm the same problem.

v2.4.4 - https://dl.dropboxusercontent.com/u/116813451/PhaserSoundTest/index_v2.4.4.html

v2.3.0 - https://dl.dropboxusercontent.com/u/116813451/PhaserSoundTest/index_v2.3.0.html

v2.4.4 decode w/o play - https://dl.dropboxusercontent.com/u/116813451/PhaserSoundTest/indexDecodeOnly_v2.4.4.html

- Open a task manager and watch the memory usage grow (chrome/webkit).

 

What I have noticed so far:
1) It is somewhere between v2.3.0 and v2.4.0a when running web audio.

2) Only in Chrome on my desktop, and in Safari on the iPad, so I'm guessing it is webkit related.

3) Creating sound objects seems to be what keeps the memory stuck. I don't know how yet. I found this out by not creating a sound object in the states. Decoding is still done, but memory is freed when changing states.
(Note: Decoding is what uses up a lot of memory. Decoding is done automatically if not specifically told not to when loading the audio. If you say so, decoding will be done when the sound is played instead, with the same effect.)

Share this post


Link to post
Share on other sites

That issue sounds like it could be the cause. It does not happen in 2.3, but something could very well have changed in when creating sounds in 2.4 to get that bug.

 

The reloading each time is intentional, it is to simulate switching between many more states where I cannot hold all the audio files decoded in the browser.

Share this post


Link to post
Share on other sites

Finally I seem to have found it.

In, at least Chrome, there is a memory leak bug when you try to stop and disconnect an AudioBufferSouceNode at the same time. This behaviour was introduced in Phaser with this commit:

https://github.com/photonstorm/phaser/commit/1990bce48b82b85b487cac0b0f990caede4d8c2d

 

A fix that seems to work is to move the disconnect parts to the onendedhandler.

if (this.externalNode){    this._sound.disconnect(this.externalNode);}else{    this._sound.disconnect(this.gainNode);}

*if you force restart audio with the play function you might need another solution.

 

Working demo: https://dl.dropboxusercontent.com/u/116813451/PhaserSoundTest/indexFix_v2.4.4.html

Share this post


Link to post
Share on other sites

Hi @trpzn

I have the code here. I hope @Anderberg doesn't mind since he made it available before:

/* Fix for Phaser to properly remove music cache START */
Phaser.Sound.prototype.onEndedHandler = function () {
    this._sound.onended = null;
    this.isPlaying = false;
    this.stop();

    if (this.externalNode)
    {
        this._sound.disconnect(this.externalNode);
    }
    else
    {
        this._sound.disconnect(this.gainNode);
    }
};

Phaser.Sound.prototype.stop = function () {

   if (this.isPlaying && this._sound)
   {
       if (this.usingWebAudio)
       {
           if (typeof this._sound.stop === 'undefined')
           {
               this._sound.noteOff(0);
           }
           else
           {
               try {
                   this._sound.stop(0);
               }
               catch (e)
               {
                   //  Thanks Android 4.4
               }
           }
       }
       else if (this.usingAudioTag)
       {
           this._sound.pause();
           this._sound.currentTime = 0;
       }
   }

   this.pendingPlayback = false;
   this.isPlaying = false;
   var prevMarker = this.currentMarker;

   if (this.currentMarker !== '')
   {
       this.onMarkerComplete.dispatch(this.currentMarker, this);
   }

   this.currentMarker = '';

   if (this.fadeTween !== null)
   {
       this.fadeTween.stop();
   }

   if (!this.paused)
   {
       this.onStop.dispatch(this, prevMarker);
   }

};
/* Fix for Phaser to properly remove music cache END */


This works fine for my project which is in Phaser version 2.6.2. As far as I know it is still an open issue, I have to assume not many people have run into this issue before but when you are making big games like mine which is over an hour long you need to be able to ditch the audio easily :)

Hope that helps.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.