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

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)