rb_gc_mark question

A

Ara.T.Howard

i reading some code attm that goes:

static VALUE convertgslmatrixToRubyMatrix(gsl_matrix *dm)
{
int i, j;
volatile VALUE result;
assert(dm);
// printf("Trying to convert dm %p\n", dm);
// printf("With size %d, %d\n", dm->size1, dm->size2);
volatile VALUE rows = rb_ary_new();
rb_gc_mark(rows);
for (i = 0; i < dm->size1; i += 1) {
volatile VALUE currow = rb_ary_new();
rb_gc_mark(currow);
rb_ary_push(rows, currow);
for (j = 0; j < dm->size2; j += 1) {
double val = gsl_matrix_get(dm, i, j);
VALUE rval = rb_float_new(val);
rb_gc_mark(rval);
rb_ary_push(currow, rval);
}
}
result = rb_funcall(cMatrix, rb_intern("rows"), 2, rows, Qnil);
rb_gc_mark(result);
return result;
}


now, everything i know says this should be something along the lines of:

static VALUE
convertgslmatrixToRubyMatrix (gsl_matrix * dm)
{
int i, j;
VALUE result;
VALUE rows = rb_ary_new ();
for (i = 0; i < dm->size1; i += 1)
{
VALUE currow = rb_ary_new ();
rb_gc_mark (currow);
rb_ary_push (rows, currow);
for (j = 0; j < dm->size2; j += 1)
{
double val = gsl_matrix_get (dm, i, j);
VALUE rval = rb_float_new (val);
rb_ary_push (currow, rval);
}
}
result = rb_funcall (cMatrix, rb_intern ("rows"), 2, rows, Qnil);
return result;
}

(please correct me if i'm wrong)

or nasty things will happen in memory right? what would it do to call
rb_gc_mark on ruby objects like this?

cheers.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| renunciation is not getting rid of the things of this world, but accepting
| that they pass away. --aitken roshi
===============================================================================
 
C

Charles Mills

Ara.T.Howard said:
i reading some code attm that goes:

static VALUE convertgslmatrixToRubyMatrix(gsl_matrix *dm)
{
int i, j;
volatile VALUE result;
assert(dm);
// printf("Trying to convert dm %p\n", dm);
// printf("With size %d, %d\n", dm->size1, dm->size2);
volatile VALUE rows = rb_ary_new();
rb_gc_mark(rows);
for (i = 0; i < dm->size1; i += 1) {
volatile VALUE currow = rb_ary_new();
rb_gc_mark(currow);
rb_ary_push(rows, currow);
for (j = 0; j < dm->size2; j += 1) {
double val = gsl_matrix_get(dm, i, j);
VALUE rval = rb_float_new(val);
rb_gc_mark(rval);
rb_ary_push(currow, rval);
}
}
result = rb_funcall(cMatrix, rb_intern("rows"), 2, rows, Qnil);
rb_gc_mark(result);
return result;
}


now, everything i know says this should be something along the lines of:

static VALUE
convertgslmatrixToRubyMatrix (gsl_matrix * dm)
{
int i, j;
VALUE result;
VALUE rows = rb_ary_new ();
for (i = 0; i < dm->size1; i += 1)
{
VALUE currow = rb_ary_new ();
rb_gc_mark (currow);
rb_ary_push (rows, currow);
for (j = 0; j < dm->size2; j += 1)
{
double val = gsl_matrix_get (dm, i, j);
VALUE rval = rb_float_new (val);
rb_ary_push (currow, rval);
}
}
result = rb_funcall (cMatrix, rb_intern ("rows"), 2, rows, Qnil);
return result;
}

(please correct me if i'm wrong)

or nasty things will happen in memory right? what would it do to call
rb_gc_mark on ruby objects like this?

You shoud just not call rb_gc_mark at all. Not sure if it even
matters, but it is possible that objects you mark using rb_gc_mark
outside of a mark and sweep cycle will hang around AFTER some of there
fields have been GCed - like an array whose elements have been GCed,
but is still -alive-. This will only happen if the stack does not
overflow when marking and the only way this could be a problem is by
using the object space API.

Anyway, hopefully whoever wrote this code hopefully wasn't modivated by
my overly paranoid/incorrect past posts about the Ruby GC.

Also you could use rb_ary_new2 to save ruby from having to resize the
array since you know the size ahead of time.

-Charlie
 
N

Nikolai Weibull

Ara.T.Howard said:
static VALUE
convertgslmatrixToRubyMatrix (gsl_matrix * dm)
{
int i, j;
VALUE result;
VALUE rows = rb_ary_new ();
for (i = 0; i < dm->size1; i += 1)
{
VALUE currow = rb_ary_new ();
rb_gc_mark (currow);
rb_ary_push (rows, currow);
for (j = 0; j < dm->size2; j += 1)
{
double val = gsl_matrix_get (dm, i, j);
VALUE rval = rb_float_new (val);
rb_ary_push (currow, rval);
}
}
result = rb_funcall (cMatrix, rb_intern ("rows"), 2, rows, Qnil);
return result;
}

I don’t understand why you need to rb_gc_mark those values. They’re
pointed to by objects on the stack, so a GC sweep won’t remove them.
Neither of the volatile specifiers in the original are needed either, as
you write (or I am definitely missing something). I don’t see how they
would be optimized away anyway. Well, actually, the 'result' variable
should be optimized away :), just return the result of the rb_funcall
immediately.

Perhaps I don’t understand what you want to do here,
nikolai
 
N

nobu.nokada

Hi,

At Tue, 17 May 2005 07:40:31 +0900,
Ara.T.Howard wrote in [ruby-talk:142850]:
i reading some code attm that goes:

static VALUE convertgslmatrixToRubyMatrix(gsl_matrix *dm)
{
int i, j;
volatile VALUE result;
assert(dm);
// printf("Trying to convert dm %p\n", dm);
// printf("With size %d, %d\n", dm->size1, dm->size2);
volatile VALUE rows = rb_ary_new();
rb_gc_mark(rows);
for (i = 0; i < dm->size1; i += 1) {
volatile VALUE currow = rb_ary_new();
rb_gc_mark(currow);
rb_ary_push(rows, currow);

GC may run while resizing rows, however many platforms don't
have the problem. And rb_gc_mark() isn't sufficient in theory
but volatile with currow avoids it, so rb_gc_mark() isn't
needed here at all.
for (j = 0; j < dm->size2; j += 1) {
double val = gsl_matrix_get(dm, i, j);
VALUE rval = rb_float_new(val);
rb_gc_mark(rval);

Therefore volatile before rval is better than rb_gc_mark() also
here.
rb_ary_push(currow, rval);
}
}
result = rb_funcall(cMatrix, rb_intern("rows"), 2, rows, Qnil);
rb_gc_mark(result);

No meanings at all.
 
A

Ara.T.Howard

You shoud just not call rb_gc_mark at all. Not sure if it even matters, but
it is possible that objects you mark using rb_gc_mark outside of a mark and
sweep cycle will hang around AFTER some of there fields have been GCed -
like an array whose elements have been GCed, but is still -alive-. This
will only happen if the stack does not overflow when marking and the only
way this could be a problem is by using the object space API.

right - so it should only be called from a mark function passed to
Data_Wrap_Struct or something like that. which is to say only ruby should
call it... is this correct?
Anyway, hopefully whoever wrote this code hopefully wasn't modivated by my
overly paranoid/incorrect past posts about the Ruby GC.

lol. i'll have to go back and read them!
Also you could use rb_ary_new2 to save ruby from having to resize the array
since you know the size ahead of time.

thanks.

cheers.


-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| renunciation is not getting rid of the things of this world, but accepting
| that they pass away. --aitken roshi
===============================================================================
 
A

Ara.T.Howard

I don’t understand why you need to rb_gc_mark those values. They’re
pointed to by objects on the stack, so a GC sweep won’t remove them.
Neither of the volatile specifiers in the original are needed either, as
you write (or I am definitely missing something). I don’t see how they
would be optimized away anyway. Well, actually, the 'result' variable
should be optimized away :), just return the result of the rb_funcall
immediately.

Perhaps I don’t understand what you want to do here,
nikolai

just wanting you to confirm exactly what i was thinking. the code was so
aggressive with rb_gc_mark that i started thinking i might be missing
something! you'll note my version didn't have them at all...

so we are in total agreement - i'm reading the code for someone else and just
trying to figure out what they thought they were doing. needless to say this
extension has some memory issues ;-)

thanks for the clarification.

cheers.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| renunciation is not getting rid of the things of this world, but accepting
| that they pass away. --aitken roshi
===============================================================================
 
A

Ara.T.Howard

Hi,

At Tue, 17 May 2005 07:40:31 +0900,
Ara.T.Howard wrote in [ruby-talk:142850]:
i reading some code attm that goes:

static VALUE convertgslmatrixToRubyMatrix(gsl_matrix *dm)
{
int i, j;
volatile VALUE result;
assert(dm);
// printf("Trying to convert dm %p\n", dm);
// printf("With size %d, %d\n", dm->size1, dm->size2);
volatile VALUE rows = rb_ary_new();
rb_gc_mark(rows);
for (i = 0; i < dm->size1; i += 1) {
volatile VALUE currow = rb_ary_new();
rb_gc_mark(currow);
rb_ary_push(rows, currow);

GC may run while resizing rows, however many platforms don't
have the problem. And rb_gc_mark() isn't sufficient in theory
but volatile with currow avoids it, so rb_gc_mark() isn't
needed here at all.

why does it matter if the GC runs while re-sizing rows? it seems like rows
would still have references to all the old rows and the new one would be
added? or are you saying that, without volatile currow could get gc'd when
rows got resized? i guess i can see that. still how would volatile help
that?
Therefore volatile before rval is better than rb_gc_mark() also
here.

you are saying ONLY volatile and no rb_gc_mark then?
No meanings at all.

right.

thanks.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| renunciation is not getting rid of the things of this world, but accepting
| that they pass away. --aitken roshi
===============================================================================
 
N

Nakada, Nobuyoshi

Hi,

At Tue, 17 May 2005 09:30:31 +0900,
why does it matter if the GC runs while re-sizing rows? it seems like rows
would still have references to all the old rows and the new one would be
added? or are you saying that, without volatile currow could get gc'd when
rows got resized? i guess i can see that. still how would volatile help
that?

I forgot that it was an already fixed bug on platforms passing
arguments by regsiters.
you are saying ONLY volatile and no rb_gc_mark then?

So you don't need volatile neither rb_gc_mak() with recent versions
of ruby even on such platforms.
 
A

Ara.T.Howard

Hi,

At Tue, 17 May 2005 09:30:31 +0900,


I forgot that it was an already fixed bug on platforms passing
arguments by regsiters.

thanks nobu - this is good to know.
So you don't need volatile neither rb_gc_mak() with recent versions of ruby
even on such platforms.

o.k. - that's great because i already stripped them ;-)

cheers.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| renunciation is not getting rid of the things of this world, but accepting
| that they pass away. --aitken roshi
===============================================================================
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top