Forum: Ruby-Gnome 2 memory leak

4913bcb685792f601ae9813b4713abb9?d=identicon&s=25 Detlef Reichl (Guest)
on 2014-03-27 20:09
(Received via mailing list)
Hi,

I stumbled over a memory leak in ruby gtk or cairo. Here is a short
example:

require 'gtk3'

class Win < Gtk::Window
    def initialize
        super
        set_default_size 800, 600
        @it = 0
        self.add_events Gdk::Event::Mask::SCROLL_MASK
        signal_connect(:scroll_event) {|object, event| redraw; false}
    end

    def redraw
        p @it
        @it += 1

        @backBuffer = Cairo::ImageSurface.new Cairo::Format::RGB24, 800,
600
        cc = Cairo::Context.new @backBuffer
        cc.antialias = :none
        cc.set_source_rgb 1.0, 1.0, 1.0
        cc.paint

        cb = self.window.create_cairo_context
        cb.set_source @backBuffer
        cb.paint
        true
    end
end

win = Win.new
win.show_all
Gtk.main


if you scroll in the window that opens, on scrolls with the mouse wheel,
after ~ 2000 ticks the memory usage on my system is around 3.6 GB. It
seems, that the image memory is not released. If I comment out the line
where the back buffer is created

        @backBuffer = Cairo::ImageSurface.new Cairo::Format::RGB24, 800,
600

the problem is gone. I don't know where to look for the solution.

Cheers, detlef
4913bcb685792f601ae9813b4713abb9?d=identicon&s=25 Detlef Reichl (Guest)
on 2014-03-27 20:48
(Received via mailing list)
Am 27.03.2014 20:08, schrieb Detlef Reichl:
> If I comment out the line
> where the back buffer is created
>
>         @backBuffer = Cairo::ImageSurface.new Cairo::Format::RGB24, 800, 600
>
> the problem is gone. I don't know where to look for the solution.
>
>

I was not precisely in my last mail. I didn't commented out the back
buffer creation, but moved it to the configure_event handler. That fixed
the problem almost for me, but the bug stays.

Cheers, detlef
8e16f7669af5b4ecfa4f2b89f32b21b6?d=identicon&s=25 Stefan Salewski (Guest)
on 2014-03-28 01:25
(Received via mailing list)
On Thu, 2014-03-27 at 20:08 +0100, Detlef Reichl wrote:
> Hi,
>
> I stumbled over a memory leak in ruby gtk or cairo.

Unfortunately I can confirm that problem.
So I really hope Kouhei Sutou or other experts can comment on it -- and
maybe on your previous question too (missing gdk_pixbuf_get_from_window)
for which I have no idea.

For your current problem: Of course generally we would not create a new
surface for each redraw, but create one in initialize method I think.
The cairo problem is depending on cc.paint, if I uncomment it in the
source below I have memory leak. But if I also uncomment #cc.destroy
and #backBuffer.destroy below I have no leak. I always wondered about
that destroy methods... I do not really know something about cairo's
memory handling and rcairo bindings -- maybe cairo painting operations
like cc.paint do increase reference count to the surface?

require 'gtk3'

class Win < Gtk::Window
    def initialize
        super
        set_default_size 800, 600
        @it = 0
        self.add_events Gdk::Event::Mask::SCROLL_MASK
        signal_connect(:scroll_event) {|object, event| redraw; false}
    end

    def redraw
        p @it
        @it += 1
        backBuffer = Cairo::ImageSurface.new Cairo::Format::RGB24, 800,
600
        cc = Cairo::Context.new backBuffer
        #cc.paint
        #cc.destroy
        #backBuffer.destroy
        #GC.start
        true
    end
end

win = Win.new
win.show_all
Gtk.main
Ee6ffca720cc428d70247dcd7377dd48?d=identicon&s=25 Kouhei Sutou (Guest)
on 2014-03-31 15:38
(Received via mailing list)
Hi,

In <53347711.3010100@gmx.org>
  "[ruby-gnome2-devel-en] memory leak" on Thu, 27 Mar 2014 20:08:01
+0100,
  Detlef Reichl <detlef.reichl@gmx.org> wrote:

> I stumbled over a memory leak in ruby gtk or cairo. Here is a short example:

Thanks for your report!
I've fixed it in rcairo at master.

--
kou
4913bcb685792f601ae9813b4713abb9?d=identicon&s=25 Detlef Reichl (Guest)
on 2014-04-04 19:37
(Received via mailing list)
Hi Kou,

I've installed rcairo von git with your fix included. For my test
program it fixed the problem, if I start the GC on regular intervals. Is
there a better solution then start the GC on my own every x draw calls?
It's only a theoretical question, cause I fixed my program on the right
way, as I already wrote.

Thanks allot! Cheers, detlef


Am 31.03.2014 15:37, schrieb Kouhei Sutou:
8e16f7669af5b4ecfa4f2b89f32b21b6?d=identicon&s=25 Stefan Salewski (Guest)
on 2014-04-04 22:31
(Received via mailing list)
On Fri, 2014-04-04 at 19:29 +0200, Detlef Reichl wrote:
> Hi Kou,
>
> I've installed rcairo von git with your fix included. For my test
> program it fixed the problem, if I start the GC on regular intervals.
> Is
> there a better solution then start the GC on my own every x draw
> calls?
> It's only a theoretical question, cause I fixed my program on the
> right
> way, as I already wrote.

I tried to find an explanation for that behaviour, and found this nice
page:

http://samsaffron.com/archive/2013/11/22/demystify...

Seems that garbage collection is triggered by size of allocated memory
-- maybe size of memory allocated by cairo is not visible to GC?

I am using Ruby 2.0 (MRI) and have the same issues as  Detlef Reichl.
Manually invoking GC when unused cairo objects exists seems to prevent
excessive heap usage, but may slow down performance.

Question: Should we manually call cairo's destroy methods when we are
done with cairo objects as in

def redraw
backBuffer = Cairo::ImageSurface.new Cairo::Format::RGB24, 800, 600
cc = Cairo::Context.new backBuffer
cc.paint
#cc.destroy
#backBuffer.destroy
#GC.start
true
end

Unfortunately rcairo's destroy methods are undocumented, so I was
wondering about it from the beginning.

Best regards,

Stefan Salewski
Ee6ffca720cc428d70247dcd7377dd48?d=identicon&s=25 Kouhei Sutou (Guest)
on 2014-04-05 01:53
(Received via mailing list)
Hi,

In <1396643100.2172.22.camel@AMD64X2.fritz.box>
  "Re: [ruby-gnome2-devel-en] memory leak" on Fri, 04 Apr 2014 22:25:00
+0200,
  Stefan Salewski <mail@ssalewski.de> wrote:

> true
> end
>
> Unfortunately rcairo's destroy methods are undocumented, so I was
> wondering about it from the beginning.

Here is the recommended way! It is Ruby-ish code. :-)

Cairo::ImageSurface.new Cairo::Format::RGB24, 800, 600 do |backBuffer|
  Cairo::Context.new backBuffer do |cc|
    cc.paint
  end
end

Thanks,
--
kou
8e16f7669af5b4ecfa4f2b89f32b21b6?d=identicon&s=25 Stefan Salewski (Guest)
on 2014-04-06 02:25
(Received via mailing list)
On Sat, 2014-04-05 at 08:52 +0900, Kouhei Sutou wrote:
> Here is the recommended way! It is Ruby-ish code. :-)
>
> Cairo::ImageSurface.new Cairo::Format::RGB24, 800, 600 do |backBuffer|
>   Cairo::Context.new backBuffer do |cc|
>     cc.paint
>   end
> end

Nice idea -- using block parameters as we do for file operation when
file is automatically closed when block terminates. Works fine, thanks.
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.