Temporary VALUE Needs to Be Protected?

Hi,

I am dealing with this puzzle. We know that we need to protect a global
variable using “rb_global_variable()” which simply calls
"rb_gc_register_address()", so that it will not be swept by Ruby gc.

Now, regarding the temporary variable such as in

static VALUE func (VALUE var1, ...)
{
    VALUE var2;
    ....
    var2 = ....
    ....
}

My feeling says that even var1 and var2 should also be protected as in

static VALUE func (VALUE var1, ...)
{
    VALUE var2;

    rb_gc_register_address (&var1);
    rb_gc_register_address (&var2);
    ....
    (some codes)
    ....
    rb_gc_unregister_address (&var1)
    rb_gc_unregister_address (&var2)
    return Qnil;
}

because the “some codes” there may invoke rb_gc(). Is this really a good
practice?

In my opinion, we have 3 options:

  1. Make sure that since a VALUE is assigned until it is disposed of no
    rb_gc() will occur. I think this is very tricky, because even a function
    such as rb_scan_args() seems to be capable of invoking gc as it has some
    "rb_ary_new…()" there.

  2. Always do the pair rb_gc_un/register_address() for each temporary
    VALUE. This will make the corresponding C code longer (more typing
    :slight_smile: ). However, this may be an acceptable solution.

  3. Have a separate Ruby heaps, where we can manually allocate and
    deallocate valid Ruby objects without intervention from the gc. This will
    probably be the ideal solution, as it is the most efficient in terms of
    execution.

Opinion, anyone?

Regards,

Bill

William Djaja Tjokroaminata wrote:

Hi,

I am dealing with this puzzle. We know that we need to protect a global
variable using “rb_global_variable()” which simply calls
“rb_gc_register_address()”, so that it will not be swept by Ruby gc.

Now, regarding the temporary variable such as in

static VALUE func (VALUE var1, ...)
{
    VALUE var2;
    ....
    var2 = ....
    ....
}

My feeling says that even var1 and var2 should also be protected as in

static VALUE func (VALUE var1, ...)
{
    VALUE var2;

    rb_gc_register_address (&var1);
    rb_gc_register_address (&var2);
    ....
    (some codes)
    ....
    rb_gc_unregister_address (&var1)
    rb_gc_unregister_address (&var2)
    return Qnil;
}

because the “some codes” there may invoke rb_gc(). Is this really a good
practice?

In my opinion, we have 3 options:

  1. Make sure that since a VALUE is assigned until it is disposed of no
    rb_gc() will occur. I think this is very tricky, because even a function
    such as rb_scan_args() seems to be capable of invoking gc as it has some
    “rb_ary_new…()” there.

  2. Always do the pair rb_gc_un/register_address() for each temporary
    VALUE. This will make the corresponding C code longer (more typing
    :slight_smile: ). However, this may be an acceptable solution.

  3. Have a separate Ruby heaps, where we can manually allocate and
    deallocate valid Ruby objects without intervention from the gc. This will
    probably be the ideal solution, as it is the most efficient in terms of
    execution.

Opinion, anyone?

Regards,

Bill
If you wanted to protect them couldn’t you use $SAFE? This is from a
newbie wondering…

Bob

Hi,

···

In message “Temporary VALUE Needs to Be Protected?” on 02/08/28, William Djaja Tjokroaminata billtj@z.glue.umd.edu writes:

Now, regarding the temporary variable such as in

static VALUE func (VALUE var1, …)
{
VALUE var2;

var2 = …

}

My feeling says that even var1 and var2 should also be protected as in

No, you don’t have to. Thanks to the “conservativeness” of the Ruby GC.

						matz.

The Ruby garbage collector scans the used part of the stack,
and registers all addresses found there. This may be too much,
but it does not matter. (That was matzs commment about the
"conservativness of the gc")

Thanks for all the information. This was not too obvious to me by looking
at gc.c.

Regards,

Bill

···

==========================================================================
Christian Szegedy szegedy@nospam.or.uni-bonn.de wrote:

The Ruby garbage collector scans the used part of the stack,
and registers all addresses found there. This may be too much,
but it does not matter. (That was matzs commment about the
“conservativness of the gc”)

What is the performance impact of Ruby’s GC being conservative?
<=> How large is the C-stack usually?

Couldn’t we use some preprocessor-magic to mark the pointers as they’re
created?

···

On Wed, Aug 28, 2002 at 06:03:41PM +0900, Christian Szegedy wrote:

The Ruby garbage collector scans the used part of the stack,
and registers all addresses found there. This may be too much,
but it does not matter. (That was matzs commment about the
“conservativness of the gc”)


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

And Bruce is effectively building BruceIX
– Alan Cox

Hi,

Yes, I probably feel the same way as you do. The more I know about the
extent of the Ruby garbage collector, the more concerned I am with its
impact on execution performance.

I think I am using Ruby in some sense not in its original intended
purpose. For my current application, I am using Ruby more like “a user
interface” then a full-blown programming tool. The core computation is
done in C and therefore for efficiency purpose I have moved a lot of data
to C struct members instead of Ruby’s “@” internal data.

As I am trying to separate Ruby object model from its memory management,
issues like this really come out. Has anybody really done a C programming
in the presence of a (mark & sweep) garbage collector (besides doing C
programming within the scripting languages)?

Regards,

Bill

···

============================================================================
Mauricio Fern?ndez batsman.geo@yahoo.com wrote:

On Wed, Aug 28, 2002 at 06:03:41PM +0900, Christian Szegedy wrote:

The Ruby garbage collector scans the used part of the stack,
and registers all addresses found there. This may be too much,
but it does not matter. (That was matzs commment about the
“conservativness of the gc”)

What is the performance impact of Ruby’s GC being conservative?
<=> How large is the C-stack usually?

Couldn’t we use some preprocessor-magic to mark the pointers as they’re
created?

William Djaja Tjokroaminata wrote:

Hi,

Yes, I probably feel the same way as you do. The more I know about the
extent of the Ruby garbage collector, the more concerned I am with its
impact on execution performance.

I think I am using Ruby in some sense not in its original intended
purpose. For my current application, I am using Ruby more like “a user
interface” then a full-blown programming tool. The core computation is
done in C and therefore for efficiency purpose I have moved a lot of data
to C struct members instead of Ruby’s “@” internal data.

As I am trying to separate Ruby object model from its memory management,
issues like this really come out. Has anybody really done a C programming
in the presence of a (mark & sweep) garbage collector (besides doing C
programming within the scripting languages)?

Regards,

Bill

The Ruby garbage collector scans the used part of the stack,
and registers all addresses found there. This may be too much,
but it does not matter. (That was matzs commment about the
“conservativness of the gc”)

What is the performance impact of Ruby’s GC being conservative?
<=> How large is the C-stack usually?

Couldn’t we use some preprocessor-magic to mark the pointers as they’re
created?

I don’t have not made any tests but my intuition says that under normal
circumstances, the size of the (used part of) stack must be fairly
negligible compared to the heap, therefore, it should not make
significant overhead.

I think, mixing C-style allocations and Ruby style Objects is fairly
trivial in Ruby. If your C-structure does not reference any Ruby
object, then you don’t need to mark anything. OTOHS, you have to mark
every referenced Ruby object. Under normal circumstances, it should
not be too hard…

Of course, Rubys GC is far from optimal, but it is still quite OK for
most applications. Besides this, you can switch it off (temporarily),
or trigger GC if you think it is appropriate in certain situations.

Regards, Christian

···

Mauricio Fern?ndez batsman.geo@yahoo.com wrote:

On Wed, Aug 28, 2002 at 06:03:41PM +0900, Christian Szegedy wrote:

That’s what I thought, we just have to avoid alloca when the GC is about
to do its job.

If Ruby were interfaced with C++ we could have a special ValueReference
type which would (un)register the pointer as needed, so that a full
stack marking wouldn’t be needed.

···

On Thu, Aug 29, 2002 at 08:51:44AM +0900, Christian Szegedy wrote:

William Djaja Tjokroaminata wrote:

Hi,

Yes, I probably feel the same way as you do. The more I know about the
extent of the Ruby garbage collector, the more concerned I am with its
impact on execution performance.

I think I am using Ruby in some sense not in its original intended
purpose. For my current application, I am using Ruby more like “a user
interface” then a full-blown programming tool. The core computation is
done in C and therefore for efficiency purpose I have moved a lot of data
to C struct members instead of Ruby’s “@” internal data.

As I am trying to separate Ruby object model from its memory management,
issues like this really come out. Has anybody really done a C programming
in the presence of a (mark & sweep) garbage collector (besides doing C
programming within the scripting languages)?

Regards,

Bill

Mauricio Fern?ndez batsman.geo@yahoo.com wrote:

On Wed, Aug 28, 2002 at 06:03:41PM +0900, Christian Szegedy wrote:

The Ruby garbage collector scans the used part of the stack,
and registers all addresses found there. This may be too much,
but it does not matter. (That was matzs commment about the
“conservativness of the gc”)

What is the performance impact of Ruby’s GC being conservative?
<=> How large is the C-stack usually?

Couldn’t we use some preprocessor-magic to mark the pointers as they’re
created?

I don’t have not made any tests but my intuition says that under normal
circumstances, the size of the (used part of) stack must be fairly
negligible compared to the heap, therefore, it should not make
significant overhead.


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

There are 3 kinds of people: those who can count & those who can’t.
– Unknown source

Hi,

Thanks for the thought; it is comforting.

Yes, initially when I started to learn how to write Ruby in C, I did
simple translation (which means converting “@data” to “rb_iv_get (obj,
@data”)”). As I learned more, most of the data has been converted to C
struct members. Actually I went too far, with the result, probably it is
hard to believe at first, that the Ruby code will look like… Python (the
language from which I switched to Ruby) :slight_smile: . I guess we really cannot
gain something for nothing…

Yes, I have minimized the marking functions only to the absolute
necessities. The only problem is, even when I control the GC manually
(switch it off temporarily), when it is time to invoke GC, the resource
taken by GC in the marking phase is really proportional to the number of
objects, whereas in fact most of the objects live until the end of the
process. This makes my application not scale well, something that is not
true when we code in C or C++. On the other hand, if I write my
application in pure C++ (I have tried it before, and it just took too
long), I will miss all the wonderful things that Ruby provides… Oh
well, I guess life is full of hard choices…

Regards,

Bill

···

============================================================================
Christian Szegedy szegedy@t-online.de wrote:

I don’t have not made any tests but my intuition says that under normal
circumstances, the size of the (used part of) stack must be fairly
negligible compared to the heap, therefore, it should not make
significant overhead.

I think, mixing C-style allocations and Ruby style Objects is fairly
trivial in Ruby. If your C-structure does not reference any Ruby
object, then you don’t need to mark anything. OTOHS, you have to mark
every referenced Ruby object. Under normal circumstances, it should
not be too hard…

Of course, Rubys GC is far from optimal, but it is still quite OK for
most applications. Besides this, you can switch it off (temporarily),
or trigger GC if you think it is appropriate in certain situations.

Regards, Christian

It sounds like your talking about smart ptr’s. I initially tried this but I
believe there would be significant overheads throughout the system.

After a lot of research I came to the conclusion that using the stack and
playing conservative is the best way to go.

···


Justin Johnson

“Mauricio Fernández” batsman.geo@yahoo.com wrote in message
news:20020829001707.GC27149@kodos…

That’s what I thought, we just have to avoid alloca when the GC is about
to do its job.

If Ruby were interfaced with C++ we could have a special ValueReference
type which would (un)register the pointer as needed, so that a full
stack marking wouldn’t be needed.


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

There are 3 kinds of people: those who can count & those who can’t.
– Unknown source