gc: make generational mode of Boehm-GC available (#9514)
parent
a3455b8433
commit
97f43d6a97
|
@ -71,10 +71,16 @@ see also `v help build`.
|
||||||
more performant without autofree.
|
more performant without autofree.
|
||||||
|
|
||||||
-gc <mode>
|
-gc <mode>
|
||||||
Use and link an optional garbage collector.
|
Use and link an optional garbage collector. Only tThe Boehm–Demers–Weiser
|
||||||
Only `-gc boehm` and `-gc boehm_leak` are supported currently.
|
garbage collector is supported currently with the following sub-options:
|
||||||
You need to install a `libgc-dev` package first, or install it manually
|
|
||||||
from source:
|
`-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
|
https://github.com/ivmai/bdwgc
|
||||||
|
|
||||||
Note, `-gc boehm` is complementary to -autofree. The Boehm garbage
|
Note, `-gc boehm` is complementary to -autofree. The Boehm garbage
|
||||||
|
|
|
@ -423,7 +423,7 @@ pub fn (mut g Gen) init() {
|
||||||
}
|
}
|
||||||
g.comptime_defines.writeln('')
|
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)')
|
g.comptime_defines.writeln('#define _VGCBOEHM (1)')
|
||||||
}
|
}
|
||||||
if g.pref.is_debug || 'debug' in g.pref.compile_defines {
|
if g.pref.is_debug || 'debug' in g.pref.compile_defines {
|
||||||
|
|
|
@ -67,12 +67,15 @@ fn (mut g Gen) gen_c_main_function_header() {
|
||||||
|
|
||||||
fn (mut g Gen) gen_c_main_header() {
|
fn (mut g Gen) gen_c_main_header() {
|
||||||
g.gen_c_main_function_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)')
|
g.writeln('#if defined(_VGCBOEHM)')
|
||||||
if g.pref.gc_mode == .boehm_leak {
|
if g.pref.gc_mode == .boehm_leak {
|
||||||
g.writeln('\tGC_set_find_leak(1);')
|
g.writeln('\tGC_set_find_leak(1);')
|
||||||
}
|
}
|
||||||
g.writeln('\tGC_INIT();')
|
g.writeln('\tGC_INIT();')
|
||||||
|
if g.pref.gc_mode == .boehm_incr {
|
||||||
|
g.writeln('\tGC_enable_incremental();')
|
||||||
|
}
|
||||||
g.writeln('#endif')
|
g.writeln('#endif')
|
||||||
}
|
}
|
||||||
g.writeln('\t_vinit(___argc, (voidptr)___argv);')
|
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
|
main_fn_start_pos := g.out.len
|
||||||
g.writeln('')
|
g.writeln('')
|
||||||
g.gen_c_main_function_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)')
|
g.writeln('#if defined(_VGCBOEHM)')
|
||||||
if g.pref.gc_mode == .boehm_leak {
|
if g.pref.gc_mode == .boehm_leak {
|
||||||
g.writeln('\tGC_set_find_leak(1);')
|
g.writeln('\tGC_set_find_leak(1);')
|
||||||
}
|
}
|
||||||
g.writeln('\tGC_INIT();')
|
g.writeln('\tGC_INIT();')
|
||||||
|
if g.pref.gc_mode == .boehm_incr {
|
||||||
|
g.writeln('\tGC_enable_incremental();')
|
||||||
|
}
|
||||||
g.writeln('#endif')
|
g.writeln('#endif')
|
||||||
}
|
}
|
||||||
g.writeln('\t_vinit(___argc, (voidptr)___argv);')
|
g.writeln('\t_vinit(___argc, (voidptr)___argv);')
|
||||||
|
|
|
@ -19,8 +19,10 @@ pub enum BuildMode {
|
||||||
|
|
||||||
pub enum GarbageCollectionMode {
|
pub enum GarbageCollectionMode {
|
||||||
no_gc
|
no_gc
|
||||||
boehm
|
boehm_full // full garbage collection mode
|
||||||
boehm_leak
|
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 {
|
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
|
build_options []string // list of options, that should be passed down to `build-module`, if needed for -usecache
|
||||||
cache_manager vcache.CacheManager
|
cache_manager vcache.CacheManager
|
||||||
is_help bool // -h, -help or --help was passed
|
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 settings:
|
||||||
checker_match_exhaustive_cutoff_limit int = 10
|
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
|
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' {
|
'boehm' {
|
||||||
res.gc_mode = .boehm
|
res.gc_mode = .boehm
|
||||||
parse_define(mut res, 'gcboehm')
|
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')
|
parse_define(mut res, 'gcboehm_leak')
|
||||||
}
|
}
|
||||||
else {
|
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)
|
exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -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
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
Loading…
Reference in New Issue