Re: [Gc] allocation with lowest overhead

Kenjiro Taura <[email protected]> Wed, 28 May 2014 15:56:44 +0900 (JST)
Newsgroups gmane.comp.programming.garbage-collection.boehmgc
Message-ID <[email protected]>
Thanks.  

(i) I will work around the bug by calling
GC_MALLOC once.  Thank you very much for this
info.

(ii) For your question about the intention of the
code, it is simply where I arrived at after
digging into the problem.  The original code
indeed allocates many objects of a similar size
(using GC_MALLOC_WORDS, for that matter).  Looking
into the problem, I simply arrived the simplest
code that reproduces what I experienced.


> 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 <[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