Re: [Gc] allocation with lowest overhead

Bruce Hoult <[email protected]> Wed, 28 May 2014 18:32:55 +1200
Newsgroups gmane.comp.programming.garbage-collection.boehmgc
Message-ID <CAMU+EkyWG_K_Z=D10MTp2NSULsEsGvcR-qhNWpg8RZ-88NtG0A@mail.gmail.com>
Hi,

First of all, it seems we have a bug in the GC. Attention Ivan :)

Code similar to yours (but fixed, see below) also crashes on OS X. If I
allocate even one object using the normal interface e.g. GC_malloc() first
then all is well, but using GC_malloc_many() immediately after GC_INIT()
crashes.

However, I'm not sure what you're expecting GC_malloc_many() to do there.
That's a completely different way of lowering the overhead of allocating
objects. It's useful if you want to allocate many objects all of the same
size e.g.

typedef struct {
  int stuff_here;
  int more_stuff[10];
} my_common_thing;

my_common_thing *new_common_thing(){
  static my_common_thing *free_list = 0;
  if (!free_list){
    printf("Refilling free list\n");
    free_list = GC_malloc_many(sizeof(my_common_thing));
  }
  my_common_thing *res = free_list;
  free_list = GC_NEXT(free_list);
  return res;
}

int main() {
  GC_INIT();
  GC_malloc(1); // avoid bug

  my_common_thing *p;
  while ((p = new_common_thing())){
    printf("%p\n", p);
  }
  return 0;
}


However if you want to allocate things of a number of different sizes and
types then the tiny_fl mechanism is appropriate.

Your original code works for me deleting the GC_malloc_many() and adding
GC_malloc(1);

Just remember the argument to GC_MALLOC_WORDS() is words not bytes...

Note: if you are using these interfaces to the GC instead of the normal
ones, really you are extending the GC itself. I'd advise putting code doing
this into its own source file and export useful functions. Don't pollute
the rest of your code with gc internal headers including unqualified things
such as NORMAL!


On Wed, May 28, 2014 at 4:00 PM, Kenjiro Taura <tau-6gqOUJIvMG0T5sms4jGy2S+Ac/[email protected]
> wrote:

> Hi Bruce,
>
> Thank you very much for your reply.
>
>
> > GC_MALLOC_WORDS will work. You don't get tiny_fl from somewhere, you
> > allocate it yourself as your own private fast-access cache of objects.
>
> So, you mean something like the following should work?
>
> #include <stdio.h>
> #include <gc/gc.h>
> #include <gc/gc_inline.h>
>
> int main() {
>   GC_INIT();
>   void * fl[GC_TINY_FREELISTS];
>   int i;
>   for (i = 0; i < GC_TINY_FREELISTS; i++) fl[i] = 0;
>   void * p;
>   p = GC_malloc_many(16);
>   GC_MALLOC_WORDS(p, 1, fl);
>   printf("%p\n", p);
>   return 0;
> }
>
> ----------------------------
>
> Here is what happend when I tried it with 7.4.0
> source (built on Ubuntu 14.04 64 bit platform).  I
> feel I must be missing something basic, but any
> further help is appreciated.
>
> (i) First, the compiler complains about undefined symbol NORMAL.
>
> export
> gc_dir=/home/tau/public_html/lecture/programming_languages/gen/progs/gc/inst
> gcc -o a_gc -DUSE_GC=1 -O0 -g -I${gc_dir}/include a.c -L${gc_dir}/lib
> -Wl,-R${gc_dir}/lib -lgc
>
> /home/tau/public_html/lecture/programming_languages/gen/progs/gc/inst/include/gc/gc_inline.h:124:26:
> error: ‘NORMAL’ undeclared (first use in this function)
>                           NORMAL, GC_malloc(grans*GC_GRANULE_BYTES), \
>
> (ii) NORMAL seems defined in private/gc_priv.h.
> Feeling I am already on a wrong track, I included
> it anyways.  It got compiled, but it results in
> segfault in the very first call to
> GC_generic_malloc_many.
>
> nanamomo:gc% ./a_gc
> Segmentation fault (core dumped)
>
> gdb says the segfault happened at the following line
> marked -----> and the value of rlh was 0x8.
>
> Reading symbols from a_gc...done.
> [New LWP 10538]
> [New LWP 10541]
> [New LWP 10539]
> [New LWP 10540]
> [Thread debugging using libthread_db enabled]
> Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
> Core was generated by `./a_gc'.
> Program terminated with signal SIGSEGV, Segmentation fault.
>
>
>         struct hblk ** rlh = ok -> ok_reclaim_list;
>         struct hblk * hbp;
>         hdr * hhdr;
>
>         rlh += lg;
> --->        while ((hbp = *rlh) != 0) {
>             hhdr = HDR(hbp);
>             *rlh = hhdr -> hb_next;
>             GC_ASSERT(hhdr -> hb_sz == lb);
>
>
> (iii) In fact, the same fault occurs when I
> directly call GC_malloc_many, not GC_MALLOC_WORDS.
> So it seems to have nothing to do with my wild
> modification of including what is supposed to be
> private.  i.e., the following program results in
> almost the same phenomenon.
>
> #include <stdio.h>
> #include <gc/gc.h>
>
> int main() {
>   void * p;
>   p = GC_malloc_many(16);
>   printf("%p\n", p);
>   return 0;
> }
>
>
> The same error occurs with the package (i.e., with
> the one I did not built from the source).
>
> >
> > As it says in the include file:
> >
> > "Tiny_fl should be an array of GC_TINY_FREELISTS void * pointers."
> >
> > If you're using GC_MALLOC_WORDS() then you can just initialise your
> tiny_fl
> > array to zeros before the first use.
> >
> >
> >
> > On Mon, May 26, 2014 at 3:57 PM, Kenjiro Taura <
> [email protected]
> >> wrote:
> >
> >> Hi,
> >>
> >> What is the fastest, yet portable way to allocate
> >> a small object in recent versions (e.g., 7.4.0)?
> >> The current interface seems more complex than what
> >> it used to be many years ago.
> >>
> >> Below, I am seeing 7.4.0 sources.
> >>
> >> I initially thought:
> >>
> >> # define GC_MALLOC_WORDS(result,n,tiny_fl)
> >>
> >> in gc_inline.h is the one I should use, but it
> >> requires tiny_fl argument I must obtain somehow.
> >>
> >> Digging into GC_malloc in thread_local_alloc.c,
> >> I found that the following line eventually gets it.
> >>
> >>     tiny_fl = ((GC_tlfs)tsd) -> normal_freelists;
> >>
> >> The next question then is how to get tsd, for
> >> which a fairly complex conditional compilation
> >> is going on.  Ignoring portability for a moment,
> >> I figured out that
> >>
> >>       tsd = GC_getspecific(GC_thread_key);
> >>
> >> is it.
> >>
> >> I tried copied and pasted it into my source and
> >> got compilation errors.  All in all, I feel I am
> >> not on the right track; they seem intentionally
> >> kept private inside a collector implementation.
> >>
> >> I started feeling I am missing some functions that
> >> portably return what needs to be passed to
> >> GC_MALLOC_WORDS, but could not find any so far.
> >>
> >> I appreciate if anybody sheds light on it.
> >> _______________________________________________
> >> bdwgc mailing list
> >> [email protected]
> >> https://lists.opendylan.org/mailman/listinfo/bdwgc
> >>
> >> --
> >> This message has been scanned for viruses and
> >> dangerous content by MailScanner, and is
> >> believed to be clean.
> >>
> >>
>
> --
> This message has been scanned for viruses and
> dangerous content by MailScanner, and is
> believed to be clean.
>
>

_______________________________________________
bdwgc mailing list
[email protected]
https://lists.opendylan.org/mailman/listinfo/bdwgc