github.com/fenixara/go@v0.0.0-20170127160404-96ea0918e670/src/runtime/mstats.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Memory statistics
     6  
     7  package runtime
     8  
     9  import (
    10  	"runtime/internal/atomic"
    11  	"runtime/internal/sys"
    12  	"unsafe"
    13  )
    14  
    15  // Statistics.
    16  // If you edit this structure, also edit type MemStats below.
    17  // Their layouts must match exactly.
    18  //
    19  // For detailed descriptions see the documentation for MemStats.
    20  // Fields that differ from MemStats are further documented here.
    21  //
    22  // Many of these fields are updated on the fly, while others are only
    23  // updated when updatememstats is called.
    24  type mstats struct {
    25  	// General statistics.
    26  	alloc       uint64 // bytes allocated and not yet freed
    27  	total_alloc uint64 // bytes allocated (even if freed)
    28  	sys         uint64 // bytes obtained from system (should be sum of xxx_sys below, no locking, approximate)
    29  	nlookup     uint64 // number of pointer lookups
    30  	nmalloc     uint64 // number of mallocs
    31  	nfree       uint64 // number of frees
    32  
    33  	// Statistics about malloc heap.
    34  	// Protected by mheap.lock
    35  	//
    36  	// In mstats, heap_sys and heap_inuse includes stack memory,
    37  	// while in MemStats stack memory is separated out from the
    38  	// heap stats.
    39  	heap_alloc    uint64 // bytes allocated and not yet freed (same as alloc above)
    40  	heap_sys      uint64 // virtual address space obtained from system
    41  	heap_idle     uint64 // bytes in idle spans
    42  	heap_inuse    uint64 // bytes in non-idle spans
    43  	heap_released uint64 // bytes released to the os
    44  	heap_objects  uint64 // total number of allocated objects
    45  
    46  	// TODO(austin): heap_released is both useless and inaccurate
    47  	// in its current form. It's useless because, from the user's
    48  	// and OS's perspectives, there's no difference between a page
    49  	// that has not yet been faulted in and a page that has been
    50  	// released back to the OS. We could fix this by considering
    51  	// newly mapped spans to be "released". It's inaccurate
    52  	// because when we split a large span for allocation, we
    53  	// "unrelease" all pages in the large span and not just the
    54  	// ones we split off for use. This is trickier to fix because
    55  	// we currently don't know which pages of a span we've
    56  	// released. We could fix it by separating "free" and
    57  	// "released" spans, but then we have to allocate from runs of
    58  	// free and released spans.
    59  
    60  	// Statistics about allocation of low-level fixed-size structures.
    61  	// Protected by FixAlloc locks.
    62  	stacks_inuse uint64 // this number is included in heap_inuse above; differs from MemStats.StackInuse
    63  	stacks_sys   uint64 // only counts newosproc0 stack in mstats; differs from MemStats.StackSys
    64  	mspan_inuse  uint64 // mspan structures
    65  	mspan_sys    uint64
    66  	mcache_inuse uint64 // mcache structures
    67  	mcache_sys   uint64
    68  	buckhash_sys uint64 // profiling bucket hash table
    69  	gc_sys       uint64
    70  	other_sys    uint64
    71  
    72  	// Statistics about garbage collector.
    73  	// Protected by mheap or stopping the world during GC.
    74  	next_gc         uint64 // goal heap_live for when next GC ends; ^0 if disabled
    75  	last_gc         uint64 // last gc (in absolute time)
    76  	pause_total_ns  uint64
    77  	pause_ns        [256]uint64 // circular buffer of recent gc pause lengths
    78  	pause_end       [256]uint64 // circular buffer of recent gc end times (nanoseconds since 1970)
    79  	numgc           uint32
    80  	numforcedgc     uint32  // number of user-forced GCs
    81  	gc_cpu_fraction float64 // fraction of CPU time used by GC
    82  	enablegc        bool
    83  	debuggc         bool
    84  
    85  	// Statistics about allocation size classes.
    86  
    87  	by_size [_NumSizeClasses]struct {
    88  		size    uint32
    89  		nmalloc uint64
    90  		nfree   uint64
    91  	}
    92  
    93  	// Statistics below here are not exported to MemStats directly.
    94  
    95  	tinyallocs uint64 // number of tiny allocations that didn't cause actual allocation; not exported to go directly
    96  
    97  	// gc_trigger is the heap size that triggers marking.
    98  	//
    99  	// When heap_live ≥ gc_trigger, the mark phase will start.
   100  	// This is also the heap size by which proportional sweeping
   101  	// must be complete.
   102  	gc_trigger uint64
   103  
   104  	// heap_live is the number of bytes considered live by the GC.
   105  	// That is: retained by the most recent GC plus allocated
   106  	// since then. heap_live <= heap_alloc, since heap_alloc
   107  	// includes unmarked objects that have not yet been swept (and
   108  	// hence goes up as we allocate and down as we sweep) while
   109  	// heap_live excludes these objects (and hence only goes up
   110  	// between GCs).
   111  	//
   112  	// This is updated atomically without locking. To reduce
   113  	// contention, this is updated only when obtaining a span from
   114  	// an mcentral and at this point it counts all of the
   115  	// unallocated slots in that span (which will be allocated
   116  	// before that mcache obtains another span from that
   117  	// mcentral). Hence, it slightly overestimates the "true" live
   118  	// heap size. It's better to overestimate than to
   119  	// underestimate because 1) this triggers the GC earlier than
   120  	// necessary rather than potentially too late and 2) this
   121  	// leads to a conservative GC rate rather than a GC rate that
   122  	// is potentially too low.
   123  	//
   124  	// Whenever this is updated, call traceHeapAlloc() and
   125  	// gcController.revise().
   126  	heap_live uint64
   127  
   128  	// heap_scan is the number of bytes of "scannable" heap. This
   129  	// is the live heap (as counted by heap_live), but omitting
   130  	// no-scan objects and no-scan tails of objects.
   131  	//
   132  	// Whenever this is updated, call gcController.revise().
   133  	heap_scan uint64
   134  
   135  	// heap_marked is the number of bytes marked by the previous
   136  	// GC. After mark termination, heap_live == heap_marked, but
   137  	// unlike heap_live, heap_marked does not change until the
   138  	// next mark termination.
   139  	heap_marked uint64
   140  }
   141  
   142  var memstats mstats
   143  
   144  // A MemStats records statistics about the memory allocator.
   145  type MemStats struct {
   146  	// General statistics.
   147  
   148  	// Alloc is bytes of allocated heap objects.
   149  	//
   150  	// This is the same as HeapAlloc (see below).
   151  	Alloc uint64
   152  
   153  	// TotalAlloc is cumulative bytes allocated for heap objects.
   154  	//
   155  	// TotalAlloc increases as heap objects are allocated, but
   156  	// unlike Alloc and HeapAlloc, it does not decrease when
   157  	// objects are freed.
   158  	TotalAlloc uint64
   159  
   160  	// Sys is the total bytes of memory obtained from the OS.
   161  	//
   162  	// Sys is the sum of the XSys fields below. Sys measures the
   163  	// virtual address space reserved by the Go runtime for the
   164  	// heap, stacks, and other internal data structures. It's
   165  	// likely that not all of the virtual address space is backed
   166  	// by physical memory at any given moment, though in general
   167  	// it all was at some point.
   168  	Sys uint64
   169  
   170  	// Lookups is the number of pointer lookups performed by the
   171  	// runtime.
   172  	//
   173  	// This is primarily useful for debugging runtime internals.
   174  	Lookups uint64
   175  
   176  	// Mallocs is the cumulative count of heap objects allocated.
   177  	// The number of live objects is Mallocs - Frees.
   178  	Mallocs uint64
   179  
   180  	// Frees is the cumulative count of heap objects freed.
   181  	Frees uint64
   182  
   183  	// Heap memory statistics.
   184  	//
   185  	// Interpreting the heap statistics requires some knowledge of
   186  	// how Go organizes memory. Go divides the virtual address
   187  	// space of the heap into "spans", which are contiguous
   188  	// regions of memory 8K or larger. A span may be in one of
   189  	// three states:
   190  	//
   191  	// An "idle" span contains no objects or other data. The
   192  	// physical memory backing an idle span can be released back
   193  	// to the OS (but the virtual address space never is), or it
   194  	// can be converted into an "in use" or "stack" span.
   195  	//
   196  	// An "in use" span contains at least one heap object and may
   197  	// have free space available to allocate more heap objects.
   198  	//
   199  	// A "stack" span is used for goroutine stacks. Stack spans
   200  	// are not considered part of the heap. A span can change
   201  	// between heap and stack memory; it is never used for both
   202  	// simultaneously.
   203  
   204  	// HeapAlloc is bytes of allocated heap objects.
   205  	//
   206  	// "Allocated" heap objects include all reachable objects, as
   207  	// well as unreachable objects that the garbage collector has
   208  	// not yet freed. Specifically, HeapAlloc increases as heap
   209  	// objects are allocated and decreases as the heap is swept
   210  	// and unreachable objects are freed. Sweeping occurs
   211  	// incrementally between GC cycles, so these two processes
   212  	// occur simultaneously, and as a result HeapAlloc tends to
   213  	// change smoothly (in contrast with the sawtooth that is
   214  	// typical of stop-the-world garbage collectors).
   215  	HeapAlloc uint64
   216  
   217  	// HeapSys is bytes of heap memory obtained from the OS.
   218  	//
   219  	// HeapSys measures the amount of virtual address space
   220  	// reserved for the heap. This includes virtual address space
   221  	// that has been reserved but not yet used, which consumes no
   222  	// physical memory, but tends to be small, as well as virtual
   223  	// address space for which the physical memory has been
   224  	// returned to the OS after it became unused (see HeapReleased
   225  	// for a measure of the latter).
   226  	//
   227  	// HeapSys estimates the largest size the heap has had.
   228  	HeapSys uint64
   229  
   230  	// HeapIdle is bytes in idle (unused) spans.
   231  	//
   232  	// Idle spans have no objects in them. These spans could be
   233  	// (and may already have been) returned to the OS, or they can
   234  	// be reused for heap allocations, or they can be reused as
   235  	// stack memory.
   236  	//
   237  	// HeapIdle minus HeapReleased estimates the amount of memory
   238  	// that could be returned to the OS, but is being retained by
   239  	// the runtime so it can grow the heap without requesting more
   240  	// memory from the OS. If this difference is significantly
   241  	// larger than the heap size, it indicates there was a recent
   242  	// transient spike in live heap size.
   243  	HeapIdle uint64
   244  
   245  	// HeapInuse is bytes in in-use spans.
   246  	//
   247  	// In-use spans have at least one object in them. These spans
   248  	// can only be used for other objects of roughly the same
   249  	// size.
   250  	//
   251  	// HeapInuse minus HeapAlloc esimates the amount of memory
   252  	// that has been dedicated to particular size classes, but is
   253  	// not currently being used. This is an upper bound on
   254  	// fragmentation, but in general this memory can be reused
   255  	// efficiently.
   256  	HeapInuse uint64
   257  
   258  	// HeapReleased is bytes of physical memory returned to the OS.
   259  	//
   260  	// This counts heap memory from idle spans that was returned
   261  	// to the OS and has not yet been reacquired for the heap.
   262  	HeapReleased uint64
   263  
   264  	// HeapObjects is the number of allocated heap objects.
   265  	//
   266  	// Like HeapAlloc, this increases as objects are allocated and
   267  	// decreases as the heap is swept and unreachable objects are
   268  	// freed.
   269  	HeapObjects uint64
   270  
   271  	// Stack memory statistics.
   272  	//
   273  	// Stacks are not considered part of the heap, but the runtime
   274  	// can reuse a span of heap memory for stack memory, and
   275  	// vice-versa.
   276  
   277  	// StackInuse is bytes in stack spans.
   278  	//
   279  	// In-use stack spans have at least one stack in them. These
   280  	// spans can only be used for other stacks of the same size.
   281  	//
   282  	// There is no StackIdle because unused stack spans are
   283  	// returned to the heap (and hence counted toward HeapIdle).
   284  	StackInuse uint64
   285  
   286  	// StackSys is bytes of stack memory obtained from the OS.
   287  	//
   288  	// StackSys is StackInuse, plus any memory obtained directly
   289  	// from the OS for OS thread stacks (which should be minimal).
   290  	StackSys uint64
   291  
   292  	// Off-heap memory statistics.
   293  	//
   294  	// The following statistics measure runtime-internal
   295  	// structures that are not allocated from heap memory (usually
   296  	// because they are part of implementing the heap). Unlike
   297  	// heap or stack memory, any memory allocated to these
   298  	// structures is dedicated to these structures.
   299  	//
   300  	// These are primarily useful for debugging runtime memory
   301  	// overheads.
   302  
   303  	// MSpanInuse is bytes of allocated mspan structures.
   304  	MSpanInuse uint64
   305  
   306  	// MSpanSys is bytes of memory obtained from the OS for mspan
   307  	// structures.
   308  	MSpanSys uint64
   309  
   310  	// MCacheInuse is bytes of allocated mcache structures.
   311  	MCacheInuse uint64
   312  
   313  	// MCacheSys is bytes of memory obtained from the OS for
   314  	// mcache structures.
   315  	MCacheSys uint64
   316  
   317  	// BuckHashSys is bytes of memory in profiling bucket hash tables.
   318  	BuckHashSys uint64
   319  
   320  	// GCSys is bytes of memory in garbage collection metadata.
   321  	GCSys uint64
   322  
   323  	// OtherSys is bytes of memory in miscellaneous off-heap
   324  	// runtime allocations.
   325  	OtherSys uint64
   326  
   327  	// Garbage collector statistics.
   328  
   329  	// NextGC is the target heap size of the next GC cycle.
   330  	//
   331  	// The garbage collector's goal is to keep HeapAlloc ≤ NextGC.
   332  	// At the end of each GC cycle, the target for the next cycle
   333  	// is computed based on the amount of reachable data and the
   334  	// value of GOGC.
   335  	NextGC uint64
   336  
   337  	// LastGC is the time the last garbage collection finished, as
   338  	// nanoseconds since 1970 (the UNIX epoch).
   339  	LastGC uint64
   340  
   341  	// PauseTotalNs is the cumulative nanoseconds in GC
   342  	// stop-the-world pauses since the program started.
   343  	//
   344  	// During a stop-the-world pause, all goroutines are paused
   345  	// and only the garbage collector can run.
   346  	PauseTotalNs uint64
   347  
   348  	// PauseNs is a circular buffer of recent GC stop-the-world
   349  	// pause times in nanoseconds.
   350  	//
   351  	// The most recent pause is at PauseNs[(NumGC+255)%256]. In
   352  	// general, PauseNs[N%256] records the time paused in the most
   353  	// recent N%256th GC cycle. There may be multiple pauses per
   354  	// GC cycle; this is the sum of all pauses during a cycle.
   355  	PauseNs [256]uint64
   356  
   357  	// PauseEnd is a circular buffer of recent GC pause end times,
   358  	// as nanoseconds since 1970 (the UNIX epoch).
   359  	//
   360  	// This buffer is filled the same way as PauseNs. There may be
   361  	// multiple pauses per GC cycle; this records the end of the
   362  	// last pause in a cycle.
   363  	PauseEnd [256]uint64
   364  
   365  	// NumGC is the number of completed GC cycles.
   366  	NumGC uint32
   367  
   368  	// NumForcedGC is the number of GC cycles that were forced by
   369  	// the application calling the GC function.
   370  	NumForcedGC uint32
   371  
   372  	// GCCPUFraction is the fraction of this program's available
   373  	// CPU time used by the GC since the program started.
   374  	//
   375  	// GCCPUFraction is expressed as a number between 0 and 1,
   376  	// where 0 means GC has consumed none of this program's CPU. A
   377  	// program's available CPU time is defined as the integral of
   378  	// GOMAXPROCS since the program started. That is, if
   379  	// GOMAXPROCS is 2 and a program has been running for 10
   380  	// seconds, its "available CPU" is 20 seconds. GCCPUFraction
   381  	// does not include CPU time used for write barrier activity.
   382  	//
   383  	// This is the same as the fraction of CPU reported by
   384  	// GODEBUG=gctrace=1.
   385  	GCCPUFraction float64
   386  
   387  	// EnableGC indicates that GC is enabled. It is always true,
   388  	// even if GOGC=off.
   389  	EnableGC bool
   390  
   391  	// DebugGC is currently unused.
   392  	DebugGC bool
   393  
   394  	// BySize reports per-size class allocation statistics.
   395  	//
   396  	// BySize[N] gives statistics for allocations of size S where
   397  	// BySize[N-1].Size < S ≤ BySize[N].Size.
   398  	//
   399  	// This does not report allocations larger than BySize[60].Size.
   400  	BySize [61]struct {
   401  		// Size is the maximum byte size of an object in this
   402  		// size class.
   403  		Size uint32
   404  
   405  		// Mallocs is the cumulative count of heap objects
   406  		// allocated in this size class. The cumulative bytes
   407  		// of allocation is Size*Mallocs. The number of live
   408  		// objects in this size class is Mallocs - Frees.
   409  		Mallocs uint64
   410  
   411  		// Frees is the cumulative count of heap objects freed
   412  		// in this size class.
   413  		Frees uint64
   414  	}
   415  }
   416  
   417  // Size of the trailing by_size array differs between mstats and MemStats,
   418  // and all data after by_size is local to runtime, not exported.
   419  // NumSizeClasses was changed, but we cannot change MemStats because of backward compatibility.
   420  // sizeof_C_MStats is the size of the prefix of mstats that
   421  // corresponds to MemStats. It should match Sizeof(MemStats{}).
   422  var sizeof_C_MStats = unsafe.Offsetof(memstats.by_size) + 61*unsafe.Sizeof(memstats.by_size[0])
   423  
   424  func init() {
   425  	var memStats MemStats
   426  	if sizeof_C_MStats != unsafe.Sizeof(memStats) {
   427  		println(sizeof_C_MStats, unsafe.Sizeof(memStats))
   428  		throw("MStats vs MemStatsType size mismatch")
   429  	}
   430  
   431  	if unsafe.Offsetof(memstats.heap_live)%8 != 0 {
   432  		println(unsafe.Offsetof(memstats.heap_live))
   433  		throw("memstats.heap_live not aligned to 8 bytes")
   434  	}
   435  }
   436  
   437  // ReadMemStats populates m with memory allocator statistics.
   438  //
   439  // The returned memory allocator statistics are up to date as of the
   440  // call to ReadMemStats. This is in contrast with a heap profile,
   441  // which is a snapshot as of the most recently completed garbage
   442  // collection cycle.
   443  func ReadMemStats(m *MemStats) {
   444  	stopTheWorld("read mem stats")
   445  
   446  	systemstack(func() {
   447  		readmemstats_m(m)
   448  	})
   449  
   450  	startTheWorld()
   451  }
   452  
   453  func readmemstats_m(stats *MemStats) {
   454  	updatememstats(nil)
   455  
   456  	// The size of the trailing by_size array differs between
   457  	// mstats and MemStats. NumSizeClasses was changed, but we
   458  	// cannot change MemStats because of backward compatibility.
   459  	memmove(unsafe.Pointer(stats), unsafe.Pointer(&memstats), sizeof_C_MStats)
   460  
   461  	// Stack numbers are part of the heap numbers, separate those out for user consumption
   462  	stats.StackSys += stats.StackInuse
   463  	stats.HeapInuse -= stats.StackInuse
   464  	stats.HeapSys -= stats.StackInuse
   465  }
   466  
   467  //go:linkname readGCStats runtime/debug.readGCStats
   468  func readGCStats(pauses *[]uint64) {
   469  	systemstack(func() {
   470  		readGCStats_m(pauses)
   471  	})
   472  }
   473  
   474  func readGCStats_m(pauses *[]uint64) {
   475  	p := *pauses
   476  	// Calling code in runtime/debug should make the slice large enough.
   477  	if cap(p) < len(memstats.pause_ns)+3 {
   478  		throw("short slice passed to readGCStats")
   479  	}
   480  
   481  	// Pass back: pauses, pause ends, last gc (absolute time), number of gc, total pause ns.
   482  	lock(&mheap_.lock)
   483  
   484  	n := memstats.numgc
   485  	if n > uint32(len(memstats.pause_ns)) {
   486  		n = uint32(len(memstats.pause_ns))
   487  	}
   488  
   489  	// The pause buffer is circular. The most recent pause is at
   490  	// pause_ns[(numgc-1)%len(pause_ns)], and then backward
   491  	// from there to go back farther in time. We deliver the times
   492  	// most recent first (in p[0]).
   493  	p = p[:cap(p)]
   494  	for i := uint32(0); i < n; i++ {
   495  		j := (memstats.numgc - 1 - i) % uint32(len(memstats.pause_ns))
   496  		p[i] = memstats.pause_ns[j]
   497  		p[n+i] = memstats.pause_end[j]
   498  	}
   499  
   500  	p[n+n] = memstats.last_gc
   501  	p[n+n+1] = uint64(memstats.numgc)
   502  	p[n+n+2] = memstats.pause_total_ns
   503  	unlock(&mheap_.lock)
   504  	*pauses = p[:n+n+3]
   505  }
   506  
   507  //go:nowritebarrier
   508  func updatememstats(stats *gcstats) {
   509  	if stats != nil {
   510  		*stats = gcstats{}
   511  	}
   512  	for mp := allm; mp != nil; mp = mp.alllink {
   513  		if stats != nil {
   514  			src := (*[unsafe.Sizeof(gcstats{}) / 8]uint64)(unsafe.Pointer(&mp.gcstats))
   515  			dst := (*[unsafe.Sizeof(gcstats{}) / 8]uint64)(unsafe.Pointer(stats))
   516  			for i, v := range src {
   517  				dst[i] += v
   518  			}
   519  			mp.gcstats = gcstats{}
   520  		}
   521  	}
   522  
   523  	memstats.mcache_inuse = uint64(mheap_.cachealloc.inuse)
   524  	memstats.mspan_inuse = uint64(mheap_.spanalloc.inuse)
   525  	memstats.sys = memstats.heap_sys + memstats.stacks_sys + memstats.mspan_sys +
   526  		memstats.mcache_sys + memstats.buckhash_sys + memstats.gc_sys + memstats.other_sys
   527  
   528  	// Calculate memory allocator stats.
   529  	// During program execution we only count number of frees and amount of freed memory.
   530  	// Current number of alive object in the heap and amount of alive heap memory
   531  	// are calculated by scanning all spans.
   532  	// Total number of mallocs is calculated as number of frees plus number of alive objects.
   533  	// Similarly, total amount of allocated memory is calculated as amount of freed memory
   534  	// plus amount of alive heap memory.
   535  	memstats.alloc = 0
   536  	memstats.total_alloc = 0
   537  	memstats.nmalloc = 0
   538  	memstats.nfree = 0
   539  	for i := 0; i < len(memstats.by_size); i++ {
   540  		memstats.by_size[i].nmalloc = 0
   541  		memstats.by_size[i].nfree = 0
   542  	}
   543  
   544  	// Flush MCache's to MCentral.
   545  	systemstack(flushallmcaches)
   546  
   547  	// Aggregate local stats.
   548  	cachestats()
   549  
   550  	// Scan all spans and count number of alive objects.
   551  	lock(&mheap_.lock)
   552  	for _, s := range mheap_.allspans {
   553  		if s.state != mSpanInUse {
   554  			continue
   555  		}
   556  		if s.sizeclass == 0 {
   557  			memstats.nmalloc++
   558  			memstats.alloc += uint64(s.elemsize)
   559  		} else {
   560  			memstats.nmalloc += uint64(s.allocCount)
   561  			memstats.by_size[s.sizeclass].nmalloc += uint64(s.allocCount)
   562  			memstats.alloc += uint64(s.allocCount) * uint64(s.elemsize)
   563  		}
   564  	}
   565  	unlock(&mheap_.lock)
   566  
   567  	// Aggregate by size class.
   568  	smallfree := uint64(0)
   569  	memstats.nfree = mheap_.nlargefree
   570  	for i := 0; i < len(memstats.by_size); i++ {
   571  		memstats.nfree += mheap_.nsmallfree[i]
   572  		memstats.by_size[i].nfree = mheap_.nsmallfree[i]
   573  		memstats.by_size[i].nmalloc += mheap_.nsmallfree[i]
   574  		smallfree += mheap_.nsmallfree[i] * uint64(class_to_size[i])
   575  	}
   576  	memstats.nfree += memstats.tinyallocs
   577  	memstats.nmalloc += memstats.nfree
   578  
   579  	// Calculate derived stats.
   580  	memstats.total_alloc = memstats.alloc + mheap_.largefree + smallfree
   581  	memstats.heap_alloc = memstats.alloc
   582  	memstats.heap_objects = memstats.nmalloc - memstats.nfree
   583  }
   584  
   585  //go:nowritebarrier
   586  func cachestats() {
   587  	for i := 0; ; i++ {
   588  		p := allp[i]
   589  		if p == nil {
   590  			break
   591  		}
   592  		c := p.mcache
   593  		if c == nil {
   594  			continue
   595  		}
   596  		purgecachedstats(c)
   597  	}
   598  }
   599  
   600  // flushmcache flushes the mcache of allp[i].
   601  //
   602  // The world must be stopped.
   603  //
   604  //go:nowritebarrier
   605  func flushmcache(i int) {
   606  	p := allp[i]
   607  	if p == nil {
   608  		return
   609  	}
   610  	c := p.mcache
   611  	if c == nil {
   612  		return
   613  	}
   614  	c.releaseAll()
   615  	stackcache_clear(c)
   616  }
   617  
   618  // flushallmcaches flushes the mcaches of all Ps.
   619  //
   620  // The world must be stopped.
   621  //
   622  //go:nowritebarrier
   623  func flushallmcaches() {
   624  	for i := 0; i < int(gomaxprocs); i++ {
   625  		flushmcache(i)
   626  	}
   627  }
   628  
   629  //go:nosplit
   630  func purgecachedstats(c *mcache) {
   631  	// Protected by either heap or GC lock.
   632  	h := &mheap_
   633  	memstats.heap_scan += uint64(c.local_scan)
   634  	c.local_scan = 0
   635  	memstats.tinyallocs += uint64(c.local_tinyallocs)
   636  	c.local_tinyallocs = 0
   637  	memstats.nlookup += uint64(c.local_nlookup)
   638  	c.local_nlookup = 0
   639  	h.largefree += uint64(c.local_largefree)
   640  	c.local_largefree = 0
   641  	h.nlargefree += uint64(c.local_nlargefree)
   642  	c.local_nlargefree = 0
   643  	for i := 0; i < len(c.local_nsmallfree); i++ {
   644  		h.nsmallfree[i] += uint64(c.local_nsmallfree[i])
   645  		c.local_nsmallfree[i] = 0
   646  	}
   647  }
   648  
   649  // Atomically increases a given *system* memory stat. We are counting on this
   650  // stat never overflowing a uintptr, so this function must only be used for
   651  // system memory stats.
   652  //
   653  // The current implementation for little endian architectures is based on
   654  // xadduintptr(), which is less than ideal: xadd64() should really be used.
   655  // Using xadduintptr() is a stop-gap solution until arm supports xadd64() that
   656  // doesn't use locks.  (Locks are a problem as they require a valid G, which
   657  // restricts their useability.)
   658  //
   659  // A side-effect of using xadduintptr() is that we need to check for
   660  // overflow errors.
   661  //go:nosplit
   662  func mSysStatInc(sysStat *uint64, n uintptr) {
   663  	if sys.BigEndian != 0 {
   664  		atomic.Xadd64(sysStat, int64(n))
   665  		return
   666  	}
   667  	if val := atomic.Xadduintptr((*uintptr)(unsafe.Pointer(sysStat)), n); val < n {
   668  		print("runtime: stat overflow: val ", val, ", n ", n, "\n")
   669  		exit(2)
   670  	}
   671  }
   672  
   673  // Atomically decreases a given *system* memory stat. Same comments as
   674  // mSysStatInc apply.
   675  //go:nosplit
   676  func mSysStatDec(sysStat *uint64, n uintptr) {
   677  	if sys.BigEndian != 0 {
   678  		atomic.Xadd64(sysStat, -int64(n))
   679  		return
   680  	}
   681  	if val := atomic.Xadduintptr((*uintptr)(unsafe.Pointer(sysStat)), uintptr(-int64(n))); val+n < n {
   682  		print("runtime: stat underflow: val ", val, ", n ", n, "\n")
   683  		exit(2)
   684  	}
   685  }