malloc.go
mbarrier.go
mbitmap.go
mcache.go
mcentral.go
mfinal.go
mfixalloc.go
mgc.go
mgcmark.go
mgcscavenge.go
mgcscavenge_test.go
mgcstack.go
mgcsweep.go
mgcsweepbuf.go
mgcwork.go
mheap.go
mkduff.go
mkfastlog2table.go
mkpreempt.go
mksizeclasses.go
mmap.go
mpagealloc.go
mpagecache.go
mpallocbits.go
mprof.go
mranges.go
msan.go
msan0.go
msize.go
mspanset.go
mstats.go
mwbbuf.go
Zero Garbage
其目的就是避免在堆上的分配行为,从而减小垃圾回收压力,提升性能。
做性能测试时使用 go test- benchmen
参数可以输出堆分配次数统计
import (
"fmt"
"github.com/shirou/gopsutil/process"
"os"
)
func main() {
mem(1)
data := new([10][1<<20]int64) // 创建一个10*1MB*8数组后的内存状态
mem(2)
// 填充该数组过程中的内存状态
for i := range data {
for x, n := 0, len(data[i]); x < n; x++ {
data[i][x] = 1
}
mem(3)
}
}
var ps *process.Process
func mem(n int) {
if ps == nil {
//NewProcess 创建一个新的进程实例, 可以通过该实例的方法,输出进行的一些信息。
p, err := process.NewProcess(int32(os.Getpid()))
if err != nil {
panic(err)
}
ps = p
}
// 输出进程的内存信息
mem, _ := ps.MemoryInfo()
fmt.Printf("%d. VMS: %d MB, RSS: %d MB \n", n, mem.VMS>>20, mem.RSS>>20)
}
在 runtime 中有两种类型的零初始化,取决于内存是否已经初始化为了一个类型安全的状态。
如果内存不在一个类型安全的状态,意思是可能由于刚被分配,并且第一次初始化使用,会含有一些垃圾值(注:这个概念在日常的 Go 代码中是遇不到的,如果学过 C 语言的同学应该能理解什么意思),那么这片内存必须使用 memclrNoHeapPointers
进行 zero-initialized
或者无指针的写。这不会触发写屏障(译者注:写屏障是 GC 中的一个概念)。
内存可以通过 typedmemclr
或者 memclrHasPointers
来写入零值,设置为类型安全的状态。这会触发写屏障。
// typedmemclr clears the typed memory at ptr with type typ. The
// memory at ptr must already be initialized (and hence in type-safe
// state). If the memory is being initialized for the first time, see
// memclrNoHeapPointers.
//
// If the caller knows that typ has pointers, it can alternatively
// call memclrHasPointers.
//
//go:nosplit
func typedmemclr(typ *_type, ptr unsafe.Pointer) {
if writeBarrier.needed && typ.ptrdata != 0 {
bulkBarrierPreWrite(uintptr(ptr), 0, typ.ptrdata)
}
memclrNoHeapPointers(ptr, typ.size)
}
// memclrHasPointers clears n bytes of typed memory starting at ptr.
// The caller must ensure that the type of the object at ptr has
// pointers, usually by checking typ.ptrdata. However, ptr
// does not have to point to the start of the allocation.
//
//go:nosplit
func memclrHasPointers(ptr unsafe.Pointer, n uintptr) {
bulkBarrierPreWrite(uintptr(ptr), 0, n)
memclrNoHeapPointers(ptr, n)
}
// memclrNoHeapPointers clears n bytes starting at ptr.
//
// Usually you should use typedmemclr. memclrNoHeapPointers should be
// used only when the caller knows that *ptr contains no heap pointers
// because either:
//
// *ptr is initialized memory and its type is pointer-free, or
//
// *ptr is uninitialized memory (e.g., memory that's being reused
// for a new allocation) and hence contains only "junk".
//
// The (CPU-specific) implementations of this function are in memclr_*.s.
//go:noescape
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)