That sounds like progress, but from what you're describing I'm not sure
you're actually testing C holding onto a reference to Ruby. As you say,
swig is helping you out with the Ruby -> C direction, but we need to be
able to make that void * reference actually point to a ruby object (that is
not pointed to by any other ruby object) and still keep it alive. If you
haven't had to integrate with the ruby GC system yet then there is a pretty
good chance you aren't actually testing this. It can be a bit tricky to
test for a couple reasons since a) you need to force the GC to run, and b)
you need to ensure there are no other references to the ruby object that is
being pointed to by the C object.

In fact now that I think about it, you really probably want a negative test
to ensure that your testing strategy is working, i.e. keep tweaking your
test until you get valgrind warnings telling you that you're accessing
freed memory. Then enable the GC integration, and verify that those
valgrind warnings go away.

For more info on how to integrate with Ruby's GC you can read this
article[1]. It's one of the few pieces of documentation I've found that
actually explain how to keep a reference from C to a Ruby object.

[1]
http://clalance.blogspot.com/2013/11/writing-ruby-extensions-in-c-part-13.html

--Rafael

On Fri, Jan 23, 2015 at 9:01 AM, Darryl L. Pierce <dpie...@redhat.com>
wrote:

> On Thu, Jan 22, 2015 at 12:08:52PM -0500, Rafael Schloming wrote:
> > The most important thing to get worked out for this is the memory
> > management semantics between C and Ruby. From what I can tell from your
> > branch, it looks like you haven't done that yet.
> <snip>
>
> My initial readings into how Ruby handles object references initially
> lead me to believe that, with Swig, we're receiving some benefit
> already WRT object management. Since Ruby uses mark and sweep rather
> than reference counts, when a Ruby object (or an C object wrapped by
> Swig as a Ruby object) goes out of reference then it'll get garbage
> collected. But I won't lie: there might be some subtle detail I'm
> missing here.
>
> I played around with this last night after your suggestion and wrote
> some stuff on a side branch [1]. It's a simple test that uses the
> following types:
>
>  * pn_rubyref_t - C type in Proton that's wrapped by Swig; holds a void *
> reference to any kind of object
>  * Farkle - a pure Ruby class
>
> I then wrote a simple app that creates 1M instances of rb_rubyref_t and
> 1M instances of Farkle as assigns a Farkle to each rb_rubyref_t. It then
> puts them each into an array, which is size limited to 100k entries (to
> allow any GC to run while the app is going).
>
> I also added finalizer function to Farkle that just outputs some text when
> the object is being garbage collected.
>
> What I see as the app runs is the output of the Farkle instances being
> garbage collected while there are still instances being created.
>
> The app then ends by sleeping and then exiting.
>
> Before and after sleeping the app outputs the number of objects (via
> ObjectSpace) exist for each type. Running it multiple times I see all of
> the pn_rubyref_t and Farkle instances being cleaned up, no memory
> leaks.
>
> I then changed things to make a circular reference between Farkle and
> pn_rubyref_t. Re-ran the tests and still see the objects getting cleaned
> up. I also ran top to keep an eye on memory usage for the ruby-mri
> process.
>
> O_o (1) [J:0/1028] mcpierce@mcpierce-laptop:cmake (0.3-fedora) $ top -b |
> grep ruby-mri
> 19989 mcpierce  20   0  188964  23228   6380 S  53.3  0.3   0:00.55
> ruby-mri
> 19989 mcpierce  20   0  202644  36892   6380 S  18.3  0.5   0:01.10
> ruby-mri
> 19989 mcpierce  20   0  207492  41784   6380 R  19.9  0.5   0:01.70
> ruby-mri
> 19989 mcpierce  20   0  227748  62108   6380 S  17.6  0.8   0:02.23
> ruby-mri
> 19989 mcpierce  20   0  229796  64020   6380 R  22.3  0.8   0:02.90
> ruby-mri
> 19989 mcpierce  20   0  233096  67188   6380 R  57.1  0.8   0:03.42
> ruby-mri
> 19989 mcpierce  20   0  233096  67188   6380 S   0.7  0.8   0:03.44
> ruby-mri
> 19989 mcpierce  20   0  233096  67188   6380 S   0.0  0.8   0:03.44
> ruby-mri
> 19989 mcpierce  20   0  233096  67188   6380 S   0.0  0.8   0:03.44
> ruby-mri
> 19989 mcpierce  20   0  233096  67188   6380 S   1.3  0.8   0:03.48
> ruby-mri
> 19989 mcpierce  20   0  235340  69564   6380 R  48.5  0.9   0:04.94
> ruby-mri
> 19989 mcpierce  20   0  235340  69564   6380 S  47.5  0.9   0:06.37
> ruby-mri
> 19989 mcpierce  20   0  235340  69564   6380 R  50.5  0.9   0:07.89
> ruby-mri
> 19989 mcpierce  20   0  235340  69564   6380 S  48.0  0.9   0:09.34
> ruby-mri
>
> I only show those lines since, after that point, the virtual memory
> footprint didn't grow for the run os the apps run.
>
>
> [1] https://github.com/mcpierce/Proton/tree/c-to-ruby-reference-gc-check
>
> --
> Darryl L. Pierce, Sr. Software Engineer @ Red Hat, Inc.
> Delivering value year after year.
> Red Hat ranks #1 in value among software vendors.
> http://www.redhat.com/promo/vendor/
>
>

Reply via email to