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

Share your advanced PureBasic knowledge/code with the community.
remi_meier
Enthusiast
Enthusiast
Posts: 468
Joined: Sat Dec 20, 2003 6:19 pm
Location: Switzerland

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

Post 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
Athlon64 3700+, 1024MB Ram, Radeon X1600
User avatar
fsw
Addict
Addict
Posts: 1603
Joined: Tue Apr 29, 2003 9:18 pm
Location: North by Northwest

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

Post 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)
remi_meier
Enthusiast
Enthusiast
Posts: 468
Joined: Sat Dec 20, 2003 6:19 pm
Location: Switzerland

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

Post 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.
Athlon64 3700+, 1024MB Ram, Radeon X1600
Post Reply