Skip to content

Commit 65f70c8

Browse files
committed
update mem
1 parent c159bf0 commit 65f70c8

File tree

1 file changed

+144
-26
lines changed

1 file changed

+144
-26
lines changed

memory.md

Lines changed: 144 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ func sysMap(v unsafe.Pointer, n uintptr, sysStat *uint64) {
309309
```
310310
┌─────────────────┬──────────────────┬────────────────────────────────┐
311311
│ │ │ │
312-
│ span (512 MB) │ bitmap (16 GB) │ arena (512 GB) │
312+
│ span (512 MB) │ bitmap (32 GB) │ arena (512 GB) │
313313
│ │ │ │
314314
└─────────────────┴──────────────────┴────────────────────────────────┘
315315
```
@@ -466,35 +466,153 @@ func mallocinit() {
466466
}
467467
```
468468

469+
跟系统要完内存之后,最后几步是:
470+
469471
```go
470-
// initialize new P's
471-
for i := int32(0); i < nprocs; i++ {
472-
pp := allp[i]
473-
if pp == nil {
474-
pp = new(p)
475-
pp.id = i
476-
pp.status = _Pgcstop
477-
pp.sudogcache = pp.sudogbuf[:0]
478-
for i := range pp.deferpool {
479-
pp.deferpool[i] = pp.deferpoolbuf[i][:0]
480-
}
481-
pp.wbBuf.reset()
482-
atomicstorep(unsafe.Pointer(&allp[i]), unsafe.Pointer(pp))
483-
}
484-
if pp.mcache == nil {
485-
if old == 0 && i == 0 {
486-
if getg().m.mcache == nil {
487-
throw("missing mcache?")
488-
}
489-
pp.mcache = getg().m.mcache // bootstrap
490-
} else {
491-
pp.mcache = allocmcache()
492-
}
493-
}
494-
}
472+
// 初始化分配器的剩余部分
473+
mheap_.init(spansStart, spansSize)
474+
_g_ := getg()
475+
_g_.m.mcache = allocmcache()
476+
```
477+
478+
这里是初始化全局的 mheap 内部的其它结构,比如 treapalloc,spanalloc,mcentral。全局三大主要部分其中的 mcentral 就是在这里分配的。
479+
480+
```go
481+
// Initialize the heap.
482+
func (h *mheap) init(spansStart, spansBytes uintptr) {
483+
h.treapalloc.init(unsafe.Sizeof(treapNode{}), nil, nil, &memstats.other_sys)
484+
h.spanalloc.init(unsafe.Sizeof(mspan{}), recordspan, unsafe.Pointer(h), &memstats.mspan_sys)
485+
h.cachealloc.init(unsafe.Sizeof(mcache{}), nil, nil, &memstats.mcache_sys)
486+
h.specialfinalizeralloc.init(unsafe.Sizeof(specialfinalizer{}), nil, nil, &memstats.other_sys)
487+
h.specialprofilealloc.init(unsafe.Sizeof(specialprofile{}), nil, nil, &memstats.other_sys)
488+
489+
// Don't zero mspan allocations. Background sweeping can
490+
// inspect a span concurrently with allocating it, so it's
491+
// important that the span's sweepgen survive across freeing
492+
// and re-allocating a span to prevent background sweeping
493+
// from improperly cas'ing it from 0.
494+
//
495+
// This is safe because mspan contains no heap pointers.
496+
h.spanalloc.zero = false
497+
498+
// h->mapcache needs no init
499+
for i := range h.free {
500+
h.free[i].init()
501+
h.busy[i].init()
502+
}
503+
504+
h.busylarge.init()
505+
for i := range h.central {
506+
h.central[i].mcentral.init(spanClass(i))
507+
}
508+
509+
sp := (*slice)(unsafe.Pointer(&h.spans))
510+
sp.array = unsafe.Pointer(spansStart)
511+
sp.len = 0
512+
sp.cap = int(spansBytes / sys.PtrSize)
513+
514+
// Map metadata structures. But don't map race detector memory
515+
// since we're not actually growing the arena here (and TSAN
516+
// gets mad if you map 0 bytes).
517+
h.setArenaUsed(h.arena_used, false)
518+
}
519+
520+
// setArenaUsed extends the usable arena to address arena_used and
521+
// maps auxiliary VM regions for any newly usable arena space.
522+
//
523+
// racemap indicates that this memory should be managed by the race
524+
// detector. racemap should be true unless this is covering a VM hole.
525+
func (h *mheap) setArenaUsed(arena_used uintptr, racemap bool) {
526+
// Map auxiliary structures *before* h.arena_used is updated.
527+
// Waiting to update arena_used until after the memory has been mapped
528+
// avoids faults when other threads try access these regions immediately
529+
// after observing the change to arena_used.
530+
531+
// Map the bitmap.
532+
h.mapBits(arena_used)
533+
534+
// Map spans array.
535+
h.mapSpans(arena_used)
536+
537+
h.arena_used = arena_used
538+
}
539+
540+
// mapBits maps any additional bitmap memory needed for the new arena memory.
541+
//
542+
// Don't call this directly. Call mheap.setArenaUsed.
543+
//
544+
//go:nowritebarrier
545+
func (h *mheap) mapBits(arena_used uintptr) {
546+
// Caller has added extra mappings to the arena.
547+
// Add extra mappings of bitmap words as needed.
548+
// We allocate extra bitmap pieces in chunks of bitmapChunk.
549+
const bitmapChunk = 8192
550+
551+
n := (arena_used - mheap_.arena_start) / heapBitmapScale
552+
n = round(n, bitmapChunk)
553+
n = round(n, physPageSize)
554+
if h.bitmap_mapped >= n {
555+
return
556+
}
557+
558+
sysMap(unsafe.Pointer(h.bitmap-n), n-h.bitmap_mapped, h.arena_reserved, &memstats.gc_sys)
559+
h.bitmap_mapped = n
560+
}
561+
562+
// mapSpans makes sure that the spans are mapped
563+
// up to the new value of arena_used.
564+
//
565+
// Don't call this directly. Call mheap.setArenaUsed.
566+
func (h *mheap) mapSpans(arena_used uintptr) {
567+
// Map spans array, PageSize at a time.
568+
n := arena_used
569+
n -= h.arena_start
570+
n = n / _PageSize * sys.PtrSize
571+
n = round(n, physPageSize)
572+
need := n / unsafe.Sizeof(h.spans[0])
573+
have := uintptr(len(h.spans))
574+
if have >= need {
575+
return
576+
}
577+
h.spans = h.spans[:need]
578+
sysMap(unsafe.Pointer(&h.spans[have]), (need-have)*unsafe.Sizeof(h.spans[0]), h.arena_reserved, &memstats.other_sys)
579+
}
580+
```
581+
582+
mcache 是个 per-P 结构,在程序启动时,会初始化化 p,并且分配对应的 mcache。实际执行是在 procresize 中:
495583

584+
```go
585+
func procresize() {
586+
// initialize new P's
587+
for i := int32(0); i < nprocs; i++ {
588+
pp := allp[i]
589+
if pp == nil {
590+
pp = new(p)
591+
pp.id = i
592+
pp.status = _Pgcstop
593+
pp.sudogcache = pp.sudogbuf[:0]
594+
for i := range pp.deferpool {
595+
pp.deferpool[i] = pp.deferpoolbuf[i][:0]
596+
}
597+
pp.wbBuf.reset()
598+
atomicstorep(unsafe.Pointer(&allp[i]), unsafe.Pointer(pp))
599+
}
600+
if pp.mcache == nil {
601+
if old == 0 && i == 0 {
602+
if getg().m.mcache == nil {
603+
throw("missing mcache?")
604+
}
605+
pp.mcache = getg().m.mcache // bootstrap
606+
} else {
607+
pp.mcache = allocmcache()
608+
}
609+
}
610+
}
611+
}
496612
```
497613

614+
这下 mcache、mcentral 和 mheap 便全部初始化完成了。
615+
498616
## 堆内存分配流程
499617

500618
```mermaid

0 commit comments

Comments
 (0)