gc: make generational mode of Boehm-GC available (#9514)

pull/9531/head
Uwe Krüger 2021-03-30 09:36:22 +02:00 committed by GitHub
parent a3455b8433
commit 97f43d6a97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 116 additions and 11 deletions

View File

@ -71,10 +71,16 @@ see also `v help build`.
more performant without autofree.
-gc <mode>
Use and link an optional garbage collector.
Only `-gc boehm` and `-gc boehm_leak` are supported currently.
You need to install a `libgc-dev` package first, or install it manually
from source:
Use and link an optional garbage collector. Only tThe BoehmDemersWeiser
garbage collector is supported currently with the following sub-options:
`-gc boehm` ........ selects the default mode for the architecture
`-gc boehm_full` ... full garbage collection mode
`-gc boehm_incr` ... incremental/generational garbage collection mode
`-gc boehm_leak` ... leak detection mode
You need to install a `libgc-dev` package first, or install it manually from:
https://github.com/ivmai/bdwgc
Note, `-gc boehm` is complementary to -autofree. The Boehm garbage

View File

@ -423,7 +423,7 @@ pub fn (mut g Gen) init() {
}
g.comptime_defines.writeln('')
}
if g.pref.gc_mode in [.boehm, .boehm_leak] {
if g.pref.gc_mode in [.boehm_full, .boehm_incr, .boehm, .boehm_leak] {
g.comptime_defines.writeln('#define _VGCBOEHM (1)')
}
if g.pref.is_debug || 'debug' in g.pref.compile_defines {

View File

@ -67,12 +67,15 @@ fn (mut g Gen) gen_c_main_function_header() {
fn (mut g Gen) gen_c_main_header() {
g.gen_c_main_function_header()
if g.pref.gc_mode in [.boehm, .boehm_leak] {
if g.pref.gc_mode in [.boehm_full, .boehm_incr, .boehm, .boehm_leak] {
g.writeln('#if defined(_VGCBOEHM)')
if g.pref.gc_mode == .boehm_leak {
g.writeln('\tGC_set_find_leak(1);')
}
g.writeln('\tGC_INIT();')
if g.pref.gc_mode == .boehm_incr {
g.writeln('\tGC_enable_incremental();')
}
g.writeln('#endif')
}
g.writeln('\t_vinit(___argc, (voidptr)___argv);')
@ -158,12 +161,15 @@ pub fn (mut g Gen) gen_c_main_for_tests() {
main_fn_start_pos := g.out.len
g.writeln('')
g.gen_c_main_function_header()
if g.pref.gc_mode in [.boehm, .boehm_leak] {
if g.pref.gc_mode in [.boehm_full, .boehm_incr, .boehm, .boehm_leak] {
g.writeln('#if defined(_VGCBOEHM)')
if g.pref.gc_mode == .boehm_leak {
g.writeln('\tGC_set_find_leak(1);')
}
g.writeln('\tGC_INIT();')
if g.pref.gc_mode == .boehm_incr {
g.writeln('\tGC_enable_incremental();')
}
g.writeln('#endif')
}
g.writeln('\t_vinit(___argc, (voidptr)___argv);')

View File

@ -19,8 +19,10 @@ pub enum BuildMode {
pub enum GarbageCollectionMode {
no_gc
boehm
boehm_leak
boehm_full // full garbage collection mode
boehm_incr // incremental garbage colletion mode
boehm // default Boehm-GC mode for architecture
boehm_leak // leak detection mode (makes `gc_check_leaks()` work)
}
pub enum OutputMode {
@ -159,7 +161,7 @@ pub mut:
build_options []string // list of options, that should be passed down to `build-module`, if needed for -usecache
cache_manager vcache.CacheManager
is_help bool // -h, -help or --help was passed
gc_mode GarbageCollectionMode = .no_gc // .no_gc, .boehm, .boehm_leak
gc_mode GarbageCollectionMode = .no_gc // .no_gc, .boehm, .boehm_leak, ...
// checker settings:
checker_match_exhaustive_cutoff_limit int = 10
}
@ -227,6 +229,16 @@ pub fn parse_args(known_external_commands []string, args []string) (&Preferences
'' {
res.gc_mode = .no_gc
}
'boehm_full' {
res.gc_mode = .boehm_full
parse_define(mut res, 'gcboehm')
parse_define(mut res, 'gcboehm_full')
}
'boehm_incr' {
res.gc_mode = .boehm_incr
parse_define(mut res, 'gcboehm')
parse_define(mut res, 'gcboehm_incr')
}
'boehm' {
res.gc_mode = .boehm
parse_define(mut res, 'gcboehm')
@ -237,7 +249,7 @@ pub fn parse_args(known_external_commands []string, args []string) (&Preferences
parse_define(mut res, 'gcboehm_leak')
}
else {
eprintln('unknown garbage collection mode, only `-gc boehm` and `-gc boehm_leak` are supported')
eprintln('unknown garbage collection mode, only `-gc boehm`, `-gc boehm_incr`, `-gc boehm_full` and `-gc boehm_leak` are supported')
exit(1)
}
}

View File

@ -0,0 +1,9 @@
#!/usr/bin/gnuplot -persist
set title "Boehm-GC: Full vs. Incremental/Generational Mode"
set xlabel "Interval #"
set ylabel "Pause Time [ms]"
set terminal pdfcairo transparent enhanced fontscale 0.5 size 5.00in, 3.00in
set output "GC_bench.pdf"
plot "boehm_full.txt" title "full GC" w i, "boehm_incr.txt" title "incr/generational GC" w i
set output
# EOF

View File

@ -0,0 +1,46 @@
import time
import rand
import math
struct MemObj {
mut:
nxt []&MemObj
}
const (
log2n = 10
n = 1 << log2n
n4 = f64(u64(1) << (4 * log2n))
)
fn waste_mem() {
mut objs := MemObj{
nxt: []&MemObj{len: n}
}
for {
sz := rand.int_in_range(10, 100000)
mut new_obj := &MemObj{
nxt: []&MemObj{len: sz}
}
sz2 := rand.int_in_range(10, 100000)
new_obj2 := &MemObj{
nxt: []&MemObj{len: sz2}
}
idx2 := rand.int_in_range(0, sz / 2)
new_obj.nxt[idx2] = new_obj2
// non-equally distributed random index
idx := int(math.sqrt(math.sqrt(rand.f64n(n4))))
objs.nxt[idx] = new_obj
}
}
fn main() {
go waste_mem()
mut last := time.sys_mono_now()
for _ in 0 .. 10_000_000 {
now := time.sys_mono_now()
interval := now - last
println(f64(interval) / f64(time.millisecond))
last = now
}
}

View File

@ -0,0 +1,26 @@
.PHONY: all
all: GC_bench.pdf
GC_bench.pdf: boehm_full.txt boehm_incr.txt
gnuplot GC_bench.plt
@echo "$@ created"
boehm_full.txt: GC_bench_full
sync
sleep 1
./$< > $@
boehm_incr.txt: GC_bench_incr
sync
sleep 1
./$< > $@
GC_bench_full: GC_bench.v
v -prod -gc boehm_full -o $@ $<
GC_bench_incr: GC_bench.v
v -prod -gc boehm_incr -o $@ $<
clean:
rm -f boehm_full.txt boehm_incr.txt GC_bench.pdf GC_bench_full GC_bench_incr