Page 1 of 1

[Linux] Garbage Collector [Boehm-Demers-Weiser]

Posted: Fri Nov 25, 2011 9:34 pm
by remi_meier
I've just tried to use the Boehm GC from within
PureBasic, and so far it seems to work nicely.
Anyone is free to do his own tests. I'm running
on Ubuntu 11.10 x64. Would be nice to know
if the include is compatible with 32 bit.

It's very easy to allocate memory and to register
a finalizer which can do the cleanup when the
memory is not referenced anymore.
Using this include it should be straightforward to
create garbage-collected libraries in PB where
you don't have to call Free*() anymore.

Here is a small example allocating ~1GB of memory
in 1MB blocks that trigger the GC ~400 times on
my machine:

Code: Select all

XIncludeFile "boehm.pbi"

GC_init()

ProcedureC finalizer(*obj, *client_data)
  Debug Str(ElapsedMilliseconds()) + " : free " + Str(*client_data)
EndProcedure

For i = 0 To 999
  *a = GC_MALLOC_(1024*1024) ; 1 MB
  
  Debug Str(ElapsedMilliseconds()) + " : alloc " + Str(i)
  GC_REGISTER_FINALIZER_(*a, @finalizer(), i, 0, 0)
Next


msg.s = "GC runs: "+Str(GC_gc_no)+#LF$
msg   + "Heap size (KB): "+Str(GC_get_heap_size() / 1024)+#LF$
msg   + "Free bytes (KB): "+Str(GC_get_free_bytes() / 1024)+#LF$
msg   + "Bytes since last collection (KB): "+Str(GC_get_bytes_since_gc() / 1024)+#LF$
msg   + "Total allocated bytes (KB): "+Str(GC_get_total_bytes() / 1024)+#LF$
MessageRequester("Stop", msg)
Maybe someone wants to experiment a bit :)

Documentation: http://www.hpl.hp.com/personal/Hans_Boe ... rface.html

Cheers,
Remi


boehm.pbi

Code: Select all

; /* 
;  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
;  * Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.
;  * Copyright 1996-1999 by Silicon Graphics.  All rights reserved.
;  * Copyright 1999 by Hewlett-Packard Company.  All rights reserved.
;  *
;  * THIS MATERIAL IS PROVIDED As IS, With ABSOLUTELY NO WARRANTY EXPRESSED
;  * Or IMPLIED.  ANY USE IS AT YOUR OWN RISK.
;  *
;  * Permission is hereby granted To use Or copy this program
;  * For any purpose,  provided the above notices are retained on all copies.
;  * Permission To modify the code And To distribute modified code is granted,
;  * provided the above notices are retained, And a notice that the code was
;  * modified is included With the above copyright notice.
;  */


; GC_word = ptr
; GC_signed_word = int

PrototypeC.i GC_OOM_FN(bytes_requested.i)
PrototypeC GC_FINALIZER_NOTIFIER()
PrototypeC GC_FINALIZATION_PROC(*obj, *client_data)
Structure GC_FINALIZATION_PROC_STRUCT
  ofn.GC_FINALIZATION_PROC
EndStructure




#GC_TIME_UNLIMITED = 999999
#GC_PROTECTS_POINTER_HEAP = 1 
#GC_PROTECTS_PTRFREE_HEAP = 2
#GC_PROTECTS_STATIC_DATA  = 4 
#GC_PROTECTS_STACK	 = 8 
#GC_PROTECTS_NONE = 0
ImportC "-lgc"
  GC_gc_no.i
  GC_parallel.l
  GC_oom_fn.GC_OOM_FN
  GC_find_leak.l
  GC_all_interior_pointers.l
  GC_quiet.l
  GC_finalize_on_demand.l
  GC_java_finalization.l
  GC_finalizer_notifier.GC_FINALIZER_NOTIFIER
  GC_dont_gc.l
  GC_dont_expand.l
  GC_use_entire_heap.l
  GC_full_freq.l
  GC_non_gc_bytes.i
  GC_no_dls.l
  GC_free_space_divisor.i
  GC_max_retries.i
  
  *GC_stackbottom
  GC_dont_precollect.l
  GC_time_limit.i
  
  
  ;/* Public procedures */
  GC_init()
  
  GC_malloc.i(size_in_bytes.i)
  GC_malloc_atomic.i(size_in_bytes.i)
  GC_malloc_uncollectable.i(size_in_bytes.i)
  GC_malloc_stubborn.i(size_in_bytes.i)
  
  GC_free(*object_addr)
  GC_change_stubborn(*ptr)
  GC_end_stubborn_change(*ptr)
  
  GC_base.i(*displaced_ptr)
  GC_size.i(*object_addr)
  GC_realloc.i(*old_obj, new_size_in_bytes.i)
  GC_expand_hp.l(number_of_bytes.i)
  
  GC_set_max_heap_size(n.i)
  GC_exclude_static_roots(*start, *finish)
  
  GC_register_displacement(n.i)
  GC_debug_register_displacement(n.i)
  GC_gcollect()
  
  GC_get_heap_size.i()
  GC_get_free_bytes.i()
  GC_get_bytes_since_gc.i()
  GC_get_total_bytes.i()
  GC_disable()
  GC_enable()
  GC_enable_incremental()
  
  GC_incremental_protection_needs.l()
  GC_collect_a_little.l()
  GC_malloc_ignore_off_page.i(lb.i)
  GC_malloc_atomic_ignore_off_page.i(lb.i)
  
  
  GC_debug_malloc.i(size_in_bytes.i, s.p-ascii, i.l)
  GC_debug_malloc_atomic.i(size_in_bytes.i, s.p-ascii, i.l)
  GC_debug_malloc_uncollectable.i(size_in_bytes.i, s.p-ascii, i.l)
  GC_debug_malloc_stubborn.i(size_in_bytes.i, s.p-ascii, i.l)
  GC_debug_malloc_ignore_off_page.i(size_in_bytes.i, s.p-ascii, i.l)
  GC_debug_malloc_atomic_ignore_off_page.i(size_in_bytes.i, s.p-ascii, i.l)
  
  GC_debug_free(*object_addr)
  GC_debug_realloc.i(*old_object, new_size_in_bytes.i, s.p-ascii, i.l)
  GC_debug_change_stubborn(*addr)
  GC_debug_end_stubborn_change(*addr)
  
  GC_debug_malloc_replacement.i(size_in_bytes.i)
  GC_debug_realloc_replacement.i(*object_addr, size_in_bytes.i)
  
  
  
  
  GC_register_finalizer(*obj, fn.GC_FINALIZATION_PROC, *cd, *ofn.GC_FINALIZATION_PROC_STRUCT, *ocd.INTEGER)
  GC_debug_register_finalizer(*obj, fn.GC_FINALIZATION_PROC, *cd, *ofn.GC_FINALIZATION_PROC_STRUCT, *ocd.INTEGER)
  
  GC_register_finalizer_ignore_self(*obj, fn.GC_FINALIZATION_PROC, *cd, *ofn.GC_FINALIZATION_PROC_STRUCT, *ocd.INTEGER)
  GC_debug_register_finalizer_ignore_self(*obj, fn.GC_FINALIZATION_PROC, *cd, *ofn.GC_FINALIZATION_PROC_STRUCT, *ocd.INTEGER)
  
  
  GC_register_disappearing_link.l(*link)
  GC_general_register_disappearing_link.l(*link, *obj)
  GC_unregister_disappearing_link.l(*link)
  GC_should_invoke_finalizers.l()
  GC_invoke_finalizers.l()
  
  GC_set_free_space_divisor.i(value.i)
  
  ; thread stuff
  GC_pthread_create.l(*new_thread, *attr, *proc, *arg)
  GC_pthread_join.l(*thread, *retval)
  GC_pthread_detach.l(*thread)
  
EndImport


CompilerIf Defined(GC_DEBUG, #PB_Constant)
  Macro GC_EXTRAS : "", #PB_Compiler_Line : EndMacro
  Macro GC_MALLOC_(sz) : GC_debug_malloc(sz, GC_EXTRAS) : EndMacro
  Macro GC_MALLOC_ATOMIC_(sz)  : GC_debug_malloc_atomic(sz, GC_EXTRAS) : EndMacro
  Macro GC_MALLOC_UNCOLLECTABLE_(sz)  : 			GC_debug_malloc_uncollectable(sz, GC_EXTRAS) : EndMacro
  Macro GC_MALLOC_IGNORE_OFF_PAGE_(sz) :  			GC_debug_malloc_ignore_off_page(sz, GC_EXTRAS) : EndMacro
  Macro GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE_(sz)  : 			GC_debug_malloc_atomic_ignore_off_page(sz, GC_EXTRAS) : EndMacro
  Macro GC_REALLOC_(old, sz)  : GC_debug_realloc(old, sz, GC_EXTRAS) : EndMacro
  Macro GC_FREE_(p) :  GC_debug_free(p) : EndMacro
  Macro GC_REGISTER_FINALIZER_(p, f, d, of, od)  : 	GC_debug_register_finalizer(p, f, d, of, od) : EndMacro
  Macro GC_REGISTER_FINALIZER_IGNORE_SELF_(p, f, d, of, od)  : 	GC_debug_register_finalizer_ignore_self(p, f, d, of, od) : EndMacro
  Macro GC_REGISTER_FINALIZER_NO_ORDER_(p, f, d, of, od)  : 	GC_debug_register_finalizer_no_order(p, f, d, of, od) : EndMacro
  Macro GC_MALLOC_STUBBORN_(sz)  : GC_debug_malloc_stubborn(sz, GC_EXTRAS) : EndMacro
  Macro GC_CHANGE_STUBBORN_(p)  : GC_debug_change_stubborn(p) : EndMacro
  Macro GC_END_STUBBORN_CHANGE_(p)  : GC_debug_end_stubborn_change(p) : EndMacro
  Macro GC_GENERAL_REGISTER_DISAPPEARING_LINK_(link, obj)  : 	GC_general_register_disappearing_link(link, GC_base(obj)) : EndMacro
  Macro GC_REGISTER_DISPLACEMENT_(n) :  GC_debug_register_displacement(n) : EndMacro
CompilerElse
  Macro GC_MALLOC_(sz)  : GC_malloc(sz) : EndMacro
  Macro GC_MALLOC_ATOMIC_(sz)  : GC_malloc_atomic(sz) : EndMacro
  Macro GC_MALLOC_UNCOLLECTABLE_(sz)  : GC_malloc_uncollectable(sz) : EndMacro
  Macro GC_MALLOC_IGNORE_OFF_PAGE_(sz)  : 			GC_malloc_ignore_off_page(sz) : EndMacro
  Macro GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE_(sz) :  			GC_malloc_atomic_ignore_off_page(sz) : EndMacro
  Macro GC_REALLOC_(old, sz)  : GC_realloc(old, sz) : EndMacro
  Macro GC_FREE_(p)  : GC_free(p) : EndMacro
  Macro GC_REGISTER_FINALIZER_(p, f, d, of, od)  : 	GC_register_finalizer(p, f, d, of, od) : EndMacro
  Macro GC_REGISTER_FINALIZER_IGNORE_SELF_(p, f, d, of, od)  : 	GC_register_finalizer_ignore_self(p, f, d, of, od) : EndMacro
  Macro GC_REGISTER_FINALIZER_NO_ORDER_(p, f, d, of, od)  : 	GC_register_finalizer_no_order(p, f, d, of, od) : EndMacro
  Macro GC_MALLOC_STUBBORN_(sz) :  GC_malloc_stubborn(sz) : EndMacro
  Macro GC_CHANGE_STUBBORN_(p)  : GC_change_stubborn(p) : EndMacro
  Macro GC_END_STUBBORN_CHANGE_(p) :  GC_end_stubborn_change(p) : EndMacro
  Macro GC_GENERAL_REGISTER_DISAPPEARING_LINK_(link, obj)  : 	GC_general_register_disappearing_link(link, obj) : EndMacro
  Macro GC_REGISTER_DISPLACEMENT_(n)  : GC_register_displacement(n) : EndMacro
CompilerEndIf

Re: [Linux] Garbage Collector [Boehm-Demers-Weiser]

Posted: Mon Nov 28, 2011 5:03 am
by fsw
Here the Hans Boehm GC as DLL for Windows:

http://ftp.digitalmars.com/Digital_Mars ... gc60a8.zip

Maybe it's useful to anyone.

BTW: the LIB for the DLL is not COFF but OMF...
(C source of GC is inside the ZIP file if there is the need to change something)

Re: [Linux] Garbage Collector [Boehm-Demers-Weiser]

Posted: Mon Nov 28, 2011 9:59 am
by remi_meier
Note: I did not take care of discrepancies between
Linux and Windows when writing the imports. Therefore
it is likely that it does not work as-is on Windows.