@@ -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