unix: use conservative GC by default

This commit does two things:

 1. It makes it possible to grow the heap on Linux and MacOS by
    allocating 1GB of virtual memory on startup and then slowly using it
    as necessary, when running out of available heap space.
 2. It switches the default GC to be the conservative GC (previously
    extalloc). This is good for consistency with other platforms that
    all use this same GC.

This makes the extalloc GC unused by default.
Этот коммит содержится в:
Ayke van Laethem 2021-05-05 14:52:15 +02:00 коммит произвёл Ron Evans
родитель c1aa152a63
коммит 959442dc82
5 изменённых файлов: 39 добавлений и 12 удалений

Просмотреть файл

@ -80,13 +80,8 @@ func (c *Config) GC() string {
if c.Target.GC != "" { if c.Target.GC != "" {
return c.Target.GC return c.Target.GC
} }
for _, tag := range c.Target.BuildTags {
if tag == "baremetal" || tag == "wasm" {
return "conservative" return "conservative"
} }
}
return "extalloc"
}
// NeedsStackObjects returns true if the compiler should insert stack objects // NeedsStackObjects returns true if the compiler should insert stack objects
// that can be traced by the garbage collector. // that can be traced by the garbage collector.

Просмотреть файл

@ -3,3 +3,11 @@
package runtime package runtime
const GOOS = "darwin" const GOOS = "darwin"
const (
// See https://github.com/golang/go/blob/master/src/syscall/zerrors_darwin_amd64.go
flag_PROT_READ = 0x1
flag_PROT_WRITE = 0x2
flag_MAP_PRIVATE = 0x2
flag_MAP_ANONYMOUS = 0x1000 // MAP_ANON
)

Просмотреть файл

@ -3,3 +3,11 @@
package runtime package runtime
const GOOS = "linux" const GOOS = "linux"
const (
// See https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/mman-common.h
flag_PROT_READ = 0x1
flag_PROT_WRITE = 0x2
flag_MAP_PRIVATE = 0x2
flag_MAP_ANONYMOUS = 0x20
)

Просмотреть файл

@ -16,6 +16,9 @@ func usleep(usec uint) int
//export malloc //export malloc
func malloc(size uintptr) unsafe.Pointer func malloc(size uintptr) unsafe.Pointer
//export mmap
func mmap(addr unsafe.Pointer, length, prot, flags, fd int, offset int) unsafe.Pointer
//export abort //export abort
func abort() func abort()

Просмотреть файл

@ -5,20 +5,33 @@
package runtime package runtime
const heapSize = 1 * 1024 * 1024 // 1MB to start var heapSize uintptr = 128 * 1024 // small amount to start
const heapMaxSize = 1 * 1024 * 1024 * 1024 // 1GB for the entire heap
var heapStart, heapEnd uintptr var heapStart, heapEnd uintptr
func preinit() { func preinit() {
heapStart = uintptr(malloc(heapSize)) // Allocate a large chunk of virtual memory. Because it is virtual, it won't
// really be allocated in RAM. Memory will only be allocated when it is
// first touched.
addr := mmap(nil, heapMaxSize, flag_PROT_READ|flag_PROT_WRITE, flag_MAP_PRIVATE|flag_MAP_ANONYMOUS, -1, 0)
heapStart = uintptr(addr)
heapEnd = heapStart + heapSize heapEnd = heapStart + heapSize
} }
// growHeap tries to grow the heap size. It returns true if it succeeds, false // growHeap tries to grow the heap size. It returns true if it succeeds, false
// otherwise. // otherwise.
func growHeap() bool { func growHeap() bool {
// At the moment, this is not possible. However it shouldn't be too if heapSize == heapMaxSize {
// difficult (at least on Linux) to allocate a large amount of virtual // Already at the max. If we run out of memory, we should consider
// memory at startup that is then slowly used. // increasing heapMaxSize on 64-bit systems.
return false return false
} }
// Grow the heap size used by the program.
heapSize = (heapSize * 4 / 3) &^ 4095 // grow by around 33%
if heapSize > heapMaxSize {
heapSize = heapMaxSize
}
setHeapEnd(heapStart + heapSize)
return true
}