Re: [Gc] allocation with lowest overhead

Ivan Maidanski <ivmai-JGs/[email protected]> Sat, 31 May 2014 13:47:43 +0400
Newsgroups gmane.comp.programming.garbage-collection.boehmgc
Message-ID <[email protected]>
 Hi Bruce,

Cherry-picked to master (with minor modification) - https://github.com/ivmai/bdwgc/commit/9854c8e873eaf736231965f890207ce2c0a5511f
Thank you. 


Thu, 29 May 2014 18:23:59 +1200 from Bruce Hoult <[email protected]>:
>This patch prevents the crash:
>
>https://github.com/ivmai/bdwgc/pull/45/commits
>
>--- a/mallocx.c
>+++ b/mallocx.c
>@@ -314,8 +314,8 @@ GC_API void GC_CALL GC_generic_malloc_many(size_t lb, int k, void **result)
>       }
>     /* First see if we can reclaim a page of objects waiting to be */
>     /* reclaimed.                                                  */
>-    {
>-        struct hblk ** rlh = ok -> ok_reclaim_list;
>+    struct hblk ** rlh = ok -> ok_reclaim_list;
>+    if (rlh){
>         struct hblk * hbp;
>         hdr * hhdr;
>
>
>
>On Wed, May 28, 2014 at 6:56 PM, Kenjiro Taura  < [email protected] > wrote:
>>
>>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.
>>>>
>>>>
>>
>>--
>>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

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