Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
Memory leaking through Sound class — Gideros Forum

Memory leaking through Sound class

YanYan Member
edited April 2022 in Bugs and issues
Every time you call sound:play() you get small memory leaking. Assuming idle game cycle should be constantly leakless we have a problem here, if a bunch of item produces many sounds like steps, roars, wing claps etc. we getting memory leak.
function showFPS()
 
	local frame = 0
	local timer = os.timer()
	local qFloor = math.floor
 
	local fps = TextField.new(nil, "")
	fps:setPosition(40, 20)
	fps:setTextColor(0xFF0000)
	fps:setScale(1.2)
 
	local function displayFps(event)
		frame = frame + 1
		if frame == 60 then
			local currentTimer = os.timer()
			fps:setText("fps: "..qFloor(60 / (currentTimer - timer)) .. "  MemUsage: " .. math.ceil(collectgarbage("count")) .. " Kb " .. " TextureUsage: " .. math.ceil(application:getTextureMemoryUsage()) .. " Kb")
 
			frame = 0
			timer = currentTimer	
		end
	end
 
	stage:addChild(fps)
	stage:addEventListener(Event.ENTER_FRAME, displayFps)
 
end
 
local sound = Sound.new("wing.wav")
local handler = function()
	sound:play(0, false, false)
end
 
local timer = Timer.new(200, 0)
 
timer:addEventListener(Event.TIMER, handler)
timer:start()
 
showFPS()
Test project attached
vk.com/yan_alex

Comments

  • hgy29hgy29 Maintainer
    Thanks, I will have a look

    Likes: Yan, MoKaLux

    +1 -1 (+2 / -0 )Share on Facebook
  • I bet it is due to this line:
    https://github.com/gideros/gideros/blob/5978063083e46218eaad83c7f04332ca4311b6aa/luabinding/audiobinder.cpp#L576
    Object is created, but never destroyed.

    If you call "collectgarbage()" right after "sound:play" there is no leaks

    Likes: MoKaLux, Yan

    +1 -1 (+2 / -0 )Share on Facebook
  • hgy29hgy29 Maintainer
    Nice catch @rrraptor, one should always call collectgarbage() before displaying memory stats to get correct figures
  • YanYan Member
    rrraptor said:

    I bet it is due to this line:
    https://github.com/gideros/gideros/blob/5978063083e46218eaad83c7f04332ca4311b6aa/luabinding/audiobinder.cpp#L576
    Object is created, but never destroyed.

    If you call "collectgarbage()" right after "sound:play" there is no leaks

    So even if we didn't make any link on a SoundChannel obj we still have a memory garbage? Is this should work like this? Isn't expensive to call GC every time I call sound play?
    vk.com/yan_alex
  • hgy29hgy29 Maintainer
    @Yan, this how lua works internally, each time something is allocated it is only freeed after a garbage collect. Since Sound:play() creates and return a SoundChannel, even if you don't need it yourself (Gideros needs it internally anyway), it will have to be garbage collected.

    But you don't need to call collectgarbage at all yourself, lua will do it internally. But if you query the memory usage, you should call collectgarbage before to avoid being misled by not yet collected data.

    Likes: Yan

    +1 -1 (+1 / -0 )Share on Facebook
  • YanYan Member
    hgy29 said:

    @Yan, this how lua works internally, each time something is allocated it is only freeed after a garbage collect. Since Sound:play() creates and return a SoundChannel, even if you don't need it yourself (Gideros needs it internally anyway), it will have to be garbage collected.

    But you don't need to call collectgarbage at all yourself, lua will do it internally. But if you query the memory usage, you should call collectgarbage before to avoid being misled by not yet collected data.

    Understand, thanks, I will keep this in mind. 👍
    vk.com/yan_alex
  • hito9hito9 Member
    Because of the large number of box2d contacts, how can we limit playing sounds at the same time? Sometimes multiplays cause loud sizzling sound. Any suggestions? By the way @rrraptor nice to see you here again.

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • YanYan Member
    edited April 2022
    hito9 said:

    Because of the large number of box2d contacts, how can we limit playing sounds at the same time? Sometimes multiplays cause loud sizzling sound. Any suggestions? By the way @rrraptor nice to see you here again.

    Did you tried different hardware? How many sounds you use at same time, thoug there is a limit on channel numbers, if I remember correctly, there are only 32 slots.

    As Gideros uses OpenAL


    Most hardware based OpenAL drivers only support as many sources as the hardware has channels. Modernly that is at least 16, probably 32 or more but can be as much as 256. There are probably sound cards that support more but 256 is the largest I've ever looked at.

    Likes: hito9

    vk.com/yan_alex
    +1 -1 (+1 / -0 )Share on Facebook
  • YanYan Member
    edited April 2022
    hito9 said:

    Because of the large number of box2d contacts, how can we limit playing sounds at the same time? Sometimes multiplays cause loud sizzling sound. Any suggestions? By the way @rrraptor nice to see you here again.

    I remember, I had the same, check format you using.

    From reference:

    Regarding the performance, you should use .wav files for sound effects and .mp3 for background music. Here are the advantages and disadvantages of these:

    WAV files: Entire sound is loaded into memory. Consumes little CPU while playing. Suitable for simultaneously played sound effects.
    MP3 files: Sound is played by reading small chunks, therefore, consumes little memory. Consumes more CPU compared to WAV files. Suitable for background music/speech.

    Likes: hito9

    vk.com/yan_alex
    +1 -1 (+1 / -0 )Share on Facebook
  • hito9hito9 Member
    Yan said:

    Did you tried different hardware? How many sounds you use at same time, thoug there is a limit on channel numbers, if I remember correctly, there are only 32 slots.

    Yes, I did. 3 to 11 sounds depending on box2d contacts. I tried both mp3 and gsrfx files, eliminating the same sounds at the same time and the duration of the sounds complicates things. I need a system like pooling sprites. It sounds easy to adapt, but it isn't.
  • MoKaLuxMoKaLux Member
    edited April 2022
    at hito9 if you want to play the sound only once on collision (box2d) then you can use something like this?
    function Player:onEnterFrame(e)
    	if self.body.isdirty then
    		local sfx = self.sndhurt:play() if sfx then sfx:setVolume(self.volume) end
    		self.body.timer = 48
    ...
    		self.body.isdirty = false
    	end
    end
    isdirty will tell the sound to play only once.

    Likes: hito9

    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
    +1 -1 (+1 / -0 )Share on Facebook
  • YanYan Member
    hito9 said:

    Yan said:

    Did you tried different hardware? How many sounds you use at same time, thoug there is a limit on channel numbers, if I remember correctly, there are only 32 slots.

    Yes, I did. 3 to 11 sounds depending on box2d contacts. I tried both mp3 and gsrfx files, eliminating the same sounds at the same time and the duration of the sounds complicates things. I need a system like pooling sprites. It sounds easy to adapt, but it isn't.
    Can you record the issue on video, so we talk definitely about same thing ?
    vk.com/yan_alex
  • hito9hito9 Member
    MoKaLux said:

    at hito9 if you want to play the sound only once on collision (box2d) then you can use something like this?

    function Player:onEnterFrame(e)
    	if self.body.isdirty then
    		local sfx = self.sndhurt:play() if sfx then sfx:setVolume(self.volume) end
    		self.body.timer = 48
    ...
    		self.body.isdirty = false
    	end
    end
    isdirty will tell the sound to play only once.
    I will try this kind of variations.
    Yan said:

    Can you record the issue on video, so we talk definitely about same thing ?

    Ok, when I record it, i will attach. I may be a little late.
  • YanYan Member
    hito9 said:

    MoKaLux said:

    at hito9 if you want to play the sound only once on collision (box2d) then you can use something like this?

    function Player:onEnterFrame(e)
    	if self.body.isdirty then
    		local sfx = self.sndhurt:play() if sfx then sfx:setVolume(self.volume) end
    		self.body.timer = 48
    ...
    		self.body.isdirty = false
    	end
    end
    isdirty will tell the sound to play only once.
    I will try this kind of variations.
    Yan said:

    Can you record the issue on video, so we talk definitely about same thing ?

    Ok, when I record it, i will attach. I may be a little late.
    In this case your body will produce o ly one sound per life, is this wanted behavior?
    vk.com/yan_alex
Sign In or Register to comment.