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