Anderberg Posted December 18, 2015 Share Posted December 18, 2015 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). Link to comment Share on other sites More sharing options...
RedPanduzer Posted December 19, 2015 Share Posted December 19, 2015 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. Link to comment Share on other sites More sharing options...
Anderberg Posted December 20, 2015 Author Share Posted December 20, 2015 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. Link to comment Share on other sites More sharing options...
Anderberg Posted January 2, 2016 Author Share Posted January 2, 2016 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.htmlv2.3.0 - https://dl.dropboxusercontent.com/u/116813451/PhaserSoundTest/index_v2.3.0.htmlv2.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.) Link to comment Share on other sites More sharing options...
chg Posted January 2, 2016 Share Posted January 2, 2016 Maybe related: https://code.google.com/p/chromium/issues/detail?id=522512 ?Edit: I notice on the network side of things you the sound files are reloaded each time they are played in your examples, not sure if that's a part of the issue Link to comment Share on other sites More sharing options...
Anderberg Posted January 3, 2016 Author Share Posted January 3, 2016 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. Link to comment Share on other sites More sharing options...
Anderberg Posted January 4, 2016 Author Share Posted January 4, 2016 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 Link to comment Share on other sites More sharing options...
fitness23 Posted September 27, 2016 Share Posted September 27, 2016 @Anderberg YES, YES, YES!!! Thank you so much for sharing your solution. This has helped me fix a bug I've had for several months Link to comment Share on other sites More sharing options...
trpzn Posted March 20, 2017 Share Posted March 20, 2017 @Anderberg I think the error is still alive, could you re upload the dropbox fix? Link to comment Share on other sites More sharing options...
fitness23 Posted March 20, 2017 Share Posted March 20, 2017 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. Link to comment Share on other sites More sharing options...
trpzn Posted March 21, 2017 Share Posted March 21, 2017 thanks you very much @fitness23 it works =D! I'll push the fix to the git repo Link to comment Share on other sites More sharing options...
Windy Posted March 9, 2018 Share Posted March 9, 2018 Hi all. i have a problem with memory leak. I try take heap snapshot of my game on Chrome. I saw: - if i load audio in preload function, my State and phaser StateManager is load again each time i reload webpage. So, memory keep increasing - If i don't load audio. Memory doesn't increase. @Anderberg @fitness23 can you help me? How to use your code? I uploaded my code, with screenshot of snapshot. Please take a look. Thank you so much. memory_leak.zip Link to comment Share on other sites More sharing options...
Windy Posted March 9, 2018 Share Posted March 9, 2018 If you don't want two download zip please tell me Link to comment Share on other sites More sharing options...
Recommended Posts