]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: document MemStats
authorAustin Clements <austin@google.com>
Sat, 10 Sep 2016 01:43:50 +0000 (21:43 -0400)
committerAustin Clements <austin@google.com>
Mon, 26 Sep 2016 22:00:50 +0000 (22:00 +0000)
This documents all fields in MemStats and more clearly documents where
mstats differs from MemStats.

Fixes #15849.

Change-Id: Ie09374bcdb3a5fdd2d25fe4bba836aaae92cb1dd
Reviewed-on: https://go-review.googlesource.com/28972
Reviewed-by: Rob Pike <r@golang.org>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
src/runtime/mstats.go

index 2f3c58358c2ee4d24d403ac18d558c9f974a80b1..69e7660cc650ba7effce2d84b30d3ebfe032a14e 100644 (file)
@@ -14,6 +14,13 @@ import (
 
 // Statistics.
 // If you edit this structure, also edit type MemStats below.
+// Their layouts must match exactly.
+//
+// For detailed descriptions see the documentation for MemStats.
+// Fields that differ from MemStats are further documented here.
+//
+// Many of these fields are updated on the fly, while others are only
+// updated when updatememstats is called.
 type mstats struct {
        // General statistics.
        alloc       uint64 // bytes allocated and not yet freed
@@ -24,18 +31,36 @@ type mstats struct {
        nfree       uint64 // number of frees
 
        // Statistics about malloc heap.
-       // protected by mheap.lock
+       // Protected by mheap.lock
+       //
+       // In mstats, heap_sys and heap_inuse includes stack memory,
+       // while in MemStats stack memory is separated out from the
+       // heap stats.
        heap_alloc    uint64 // bytes allocated and not yet freed (same as alloc above)
-       heap_sys      uint64 // bytes obtained from system
+       heap_sys      uint64 // virtual address space obtained from system
        heap_idle     uint64 // bytes in idle spans
        heap_inuse    uint64 // bytes in non-idle spans
        heap_released uint64 // bytes released to the os
        heap_objects  uint64 // total number of allocated objects
 
+       // TODO(austin): heap_released is both useless and inaccurate
+       // in its current form. It's useless because, from the user's
+       // and OS's perspectives, there's no difference between a page
+       // that has not yet been faulted in and a page that has been
+       // released back to the OS. We could fix this by considering
+       // newly mapped spans to be "released". It's inaccurate
+       // because when we split a large span for allocation, we
+       // "unrelease" all pages in the large span and not just the
+       // ones we split off for use. This is trickier to fix because
+       // we currently don't know which pages of a span we've
+       // released. We could fix it by separating "free" and
+       // "released" spans, but then we have to allocate from runs of
+       // free and released spans.
+
        // Statistics about allocation of low-level fixed-size structures.
        // Protected by FixAlloc locks.
-       stacks_inuse uint64 // this number is included in heap_inuse above
-       stacks_sys   uint64 // always 0 in mstats
+       stacks_inuse uint64 // this number is included in heap_inuse above; differs from MemStats.StackInuse
+       stacks_sys   uint64 // only counts newosproc0 stack in mstats; differs from MemStats.StackSys
        mspan_inuse  uint64 // mspan structures
        mspan_sys    uint64
        mcache_inuse uint64 // mcache structures
@@ -64,7 +89,7 @@ type mstats struct {
                nfree   uint64
        }
 
-       // Statistics below here are not exported to Go directly.
+       // Statistics below here are not exported to MemStats directly.
 
        tinyallocs uint64 // number of tiny allocations that didn't cause actual allocation; not exported to go directly
 
@@ -118,47 +143,254 @@ var memstats mstats
 // A MemStats records statistics about the memory allocator.
 type MemStats struct {
        // General statistics.
-       Alloc      uint64 // bytes allocated and not yet freed
-       TotalAlloc uint64 // bytes allocated (even if freed)
-       Sys        uint64 // bytes obtained from system (sum of XxxSys below)
-       Lookups    uint64 // number of pointer lookups
-       Mallocs    uint64 // number of mallocs
-       Frees      uint64 // number of frees
-
-       // Main allocation heap statistics.
-       HeapAlloc    uint64 // bytes allocated and not yet freed (same as Alloc above)
-       HeapSys      uint64 // bytes obtained from system
-       HeapIdle     uint64 // bytes in idle spans
-       HeapInuse    uint64 // bytes in non-idle span
-       HeapReleased uint64 // bytes released to the OS
-       HeapObjects  uint64 // total number of allocated objects
-
-       // Low-level fixed-size structure allocator statistics.
-       //      Inuse is bytes used now.
-       //      Sys is bytes obtained from system.
-       StackInuse  uint64 // bytes used by stack allocator
-       StackSys    uint64
-       MSpanInuse  uint64 // mspan structures
-       MSpanSys    uint64
-       MCacheInuse uint64 // mcache structures
-       MCacheSys   uint64
-       BuckHashSys uint64 // profiling bucket hash table
-       GCSys       uint64 // GC metadata
-       OtherSys    uint64 // other system allocations
+
+       // Alloc is bytes of allocated heap objects.
+       //
+       // This is the same as HeapAlloc (see below).
+       Alloc uint64
+
+       // TotalAlloc is cumulative bytes allocated for heap objects.
+       //
+       // TotalAlloc increases as heap objects are allocated, but
+       // unlike Alloc and HeapAlloc, it does not decrease when
+       // objects are freed.
+       TotalAlloc uint64
+
+       // Sys is the total bytes of memory obtained from the OS.
+       //
+       // Sys is the sum of the XSys fields below. Sys measures the
+       // virtual address space reserved by the Go runtime for the
+       // heap, stacks, and other internal data structures. It's
+       // likely that not all of the virtual address space is backed
+       // by physical memory at any given moment, though in general
+       // it all was at some point.
+       Sys uint64
+
+       // Lookups is the number of pointer lookups performed by the
+       // runtime.
+       //
+       // This is primarily useful for debugging runtime internals.
+       Lookups uint64
+
+       // Mallocs is the cumulative count of heap objects allocated.
+       Mallocs uint64
+
+       // Frees is the cumulative count of heap objects freed.
+       Frees uint64
+
+       // Heap memory statistics.
+       //
+       // Interpreting the heap statistics requires some knowledge of
+       // how Go organizes memory. Go divides the virtual address
+       // space of the heap into "spans", which are contiguous
+       // regions of memory 8K or larger. A span may be in one of
+       // three states:
+       //
+       // An "idle" span contains no objects or other data. The
+       // physical memory backing an idle span can be released back
+       // to the OS (but the virtual address space never is), or it
+       // can be converted into an "in use" or "stack" span.
+       //
+       // An "in use" span contains at least one heap object and may
+       // have free space available to allocate more heap objects.
+       //
+       // A "stack" span is used for goroutine stacks. Stack spans
+       // are not considered part of the heap. A span can change
+       // between heap and stack memory; it is never used for both
+       // simultaneously.
+
+       // HeapAlloc is bytes of allocated heap objects.
+       //
+       // "Allocated" heap objects include all reachable objects, as
+       // well as unreachable objects that the garbage collector has
+       // not yet freed. Specifically, HeapAlloc increases as heap
+       // objects are allocated and decreases as the heap is swept
+       // and unreachable objects are freed. Sweeping occurs
+       // incrementally between GC cycles, so these two processes
+       // occur simultaneously, and as a result HeapAlloc tends to
+       // change smoothly (in contrast with the sawtooth that is
+       // typical of stop-the-world garbage collectors).
+       HeapAlloc uint64
+
+       // HeapSys is bytes of heap memory obtained from the OS.
+       //
+       // HeapSys measures the amount of virtual address space
+       // reserved for the heap. This includes virtual address space
+       // that has been reserved but not yet used, which consumes no
+       // physical memory, but tends to be small, as well as virtual
+       // address space for which the physical memory has been
+       // returned to the OS after it became unused (see HeapReleased
+       // for a measure of the latter).
+       //
+       // HeapSys estimates the largest size the heap has had.
+       HeapSys uint64
+
+       // HeapIdle is bytes in idle (unused) spans.
+       //
+       // Idle spans have no objects in them. These spans could be
+       // (and may already have been) returned to the OS, or they can
+       // be reused for heap allocations, or they can be reused as
+       // stack memory.
+       //
+       // HeapIdle minus HeapReleased estimates the amount of memory
+       // that could be returned to the OS, but is being retained by
+       // the runtime so it can grow the heap without requesting more
+       // memory from the OS. If this difference is significantly
+       // larger than the heap size, it indicates there was a recent
+       // transient spike in live heap size.
+       HeapIdle uint64
+
+       // HeapInuse is bytes in in-use spans.
+       //
+       // In-use spans have at least one object in them. These spans
+       // can only be used for other objects of roughly the same
+       // size.
+       //
+       // HeapInuse minus HeapAlloc esimates the amount of memory
+       // that has been dedicated to particular size classes, but is
+       // not currently being used. This is an upper bound on
+       // fragmentation, but in general this memory can be reused
+       // efficiently.
+       HeapInuse uint64
+
+       // HeapReleased is bytes of physical memory returned to the OS.
+       //
+       // This counts heap memory from idle spans that was returned
+       // to the OS and has not yet been reacquired for the heap.
+       HeapReleased uint64
+
+       // HeapObjects is the number of allocated heap objects.
+       //
+       // Like HeapAlloc, this increases as objects are allocated and
+       // decreases as the heap is swept and unreachable objects are
+       // freed.
+       HeapObjects uint64
+
+       // Stack memory statistics.
+       //
+       // Stacks are not considered part of the heap, but the runtime
+       // can reuse a span of heap memory for stack memory, and
+       // vice-versa.
+
+       // StackInuse is bytes in stack spans.
+       //
+       // In-use stack spans have at least one stack in them. These
+       // spans can only be used for other stacks of the same size.
+       //
+       // There is no StackIdle because unused stack spans are
+       // returned to the heap (and hence counted toward HeapIdle).
+       StackInuse uint64
+
+       // StackSys is bytes of stack memory obtained from the OS.
+       //
+       // StackSys is StackInuse, plus any memory obtained directly
+       // from the OS for OS thread stacks (which should be minimal).
+       StackSys uint64
+
+       // Off-heap memory statistics.
+       //
+       // The following statistics measure runtime-internal
+       // structures that are not allocated from heap memory (usually
+       // because they are part of implementing the heap). Unlike
+       // heap or stack memory, any memory allocated to these
+       // structures is dedicated to these structures.
+       //
+       // These are primarily useful for debugging runtime memory
+       // overheads.
+
+       // MSpanInuse is bytes of allocated mspan structures.
+       MSpanInuse uint64
+
+       // MSpanSys is bytes of memory obtained from the OS for mspan
+       // structures.
+       MSpanSys uint64
+
+       // MCacheInuse is bytes of allocated mcache structures.
+       MCacheInuse uint64
+
+       // MCacheSys is bytes of memory obtained from the OS for
+       // mcache structures.
+       MCacheSys uint64
+
+       // BuckHashSys is bytes of memory in profiling bucket hash tables.
+       BuckHashSys uint64
+
+       // GCSys is bytes of memory in garbage collection metadata.
+       GCSys uint64
+
+       // OtherSys is bytes of memory in miscellaneous off-heap
+       // runtime allocations.
+       OtherSys uint64
 
        // Garbage collector statistics.
-       NextGC        uint64 // next collection will happen when HeapAlloc ≥ this amount
-       LastGC        uint64 // end time of last collection (nanoseconds since 1970)
-       PauseTotalNs  uint64
-       PauseNs       [256]uint64 // circular buffer of recent GC pause durations, most recent at [(NumGC+255)%256]
-       PauseEnd      [256]uint64 // circular buffer of recent GC pause end times
-       NumGC         uint32
-       GCCPUFraction float64 // fraction of CPU time used by GC
-       EnableGC      bool
-       DebugGC       bool
-
-       // Per-size allocation statistics.
-       // 61 is NumSizeClasses in the C code.
+
+       // NextGC is the target heap size of the next GC cycle.
+       //
+       // The garbage collector's goal is to keep HeapAlloc ≤ NextGC.
+       // At the end of each GC cycle, the target for the next cycle
+       // is computed based on the amount of reachable data and the
+       // value of GOGC.
+       NextGC uint64
+
+       // LastGC is the time the last garbage collection finished, as
+       // nanoseconds since 1970 (the UNIX epoch).
+       LastGC uint64
+
+       // PauseTotalNs is the cumulative nanoseconds in GC
+       // stop-the-world pauses since the program started.
+       //
+       // During a stop-the-world pause, all goroutines are paused
+       // and only the garbage collector can run.
+       PauseTotalNs uint64
+
+       // PauseNs is a circular buffer of recent GC stop-the-world
+       // pause times in nanoseconds.
+       //
+       // The most recent pause is at PauseNs[(NumGC+255)%256]. In
+       // general, PauseNs[N%256] records the time paused in the most
+       // recent N%256th GC cycle. There may be multiple pauses per
+       // GC cycle; this is the sum of all pauses during a cycle.
+       PauseNs [256]uint64
+
+       // PauseEnd is a circular buffer of recent GC pause end times,
+       // as nanoseconds since 1970 (the UNIX epoch).
+       //
+       // This buffer is filled the same way as PauseNs. There may be
+       // multiple pauses per GC cycle; this records the end of the
+       // last pause in a cycle.
+       PauseEnd [256]uint64
+
+       // NumGC is the number of completed GC cycles.
+       NumGC uint32
+
+       // GCCPUFraction is the fraction of this program's available
+       // CPU time used by the GC since the program started.
+       //
+       // GCCPUFraction is expressed as a number between 0 and 1,
+       // where 0 means GC has consumed none of this program's CPU. A
+       // program's available CPU time is defined as the integral of
+       // GOMAXPROCS since the program started. That is, if
+       // GOMAXPROCS is 2 and a program has been running for 10
+       // seconds, its "available CPU" is 20 seconds. GCCPUFraction
+       // does not include CPU time used for write barrier activity.
+       //
+       // This is the same as the fraction of CPU reported by
+       // GODEBUG=gctrace=1.
+       GCCPUFraction float64
+
+       // EnableGC indicates that GC is enabled. It is always true,
+       // even if GOGC=off.
+       EnableGC bool
+
+       // DebugGC is currently unused.
+       DebugGC bool
+
+       // BySize reports per-size class allocation statistics.
+       //
+       // BySize[N] gives statistics for allocations of size S where
+       // BySize[N-1].Size < S ≤ BySize[N].Size.
+       //
+       // This does not report allocations larger than BySize[60].Size.
        BySize [61]struct {
                Size    uint32
                Mallocs uint64
@@ -166,10 +398,11 @@ type MemStats struct {
        }
 }
 
-// Size of the trailing by_size array differs between Go and C,
+// Size of the trailing by_size array differs between mstats and MemStats,
 // and all data after by_size is local to runtime, not exported.
-// NumSizeClasses was changed, but we cannot change Go struct because of backward compatibility.
-// sizeof_C_MStats is what C thinks about size of Go struct.
+// NumSizeClasses was changed, but we cannot change MemStats because of backward compatibility.
+// sizeof_C_MStats is the size of the prefix of mstats that
+// corresponds to MemStats. It should match Sizeof(MemStats{}).
 var sizeof_C_MStats = unsafe.Offsetof(memstats.by_size) + 61*unsafe.Sizeof(memstats.by_size[0])
 
 func init() {
@@ -181,6 +414,11 @@ func init() {
 }
 
 // ReadMemStats populates m with memory allocator statistics.
+//
+// The returned memory allocator statistics are up to date as of the
+// call to ReadMemStats. This is in contrast with a heap profile,
+// which is a snapshot as of the most recently completed garbage
+// collection cycle.
 func ReadMemStats(m *MemStats) {
        stopTheWorld("read mem stats")
 
@@ -194,8 +432,9 @@ func ReadMemStats(m *MemStats) {
 func readmemstats_m(stats *MemStats) {
        updatememstats(nil)
 
-       // Size of the trailing by_size array differs between Go and C,
-       // NumSizeClasses was changed, but we cannot change Go struct because of backward compatibility.
+       // The size of the trailing by_size array differs between
+       // mstats and MemStats. NumSizeClasses was changed, but we
+       // cannot change MemStats because of backward compatibility.
        memmove(unsafe.Pointer(stats), unsafe.Pointer(&memstats), sizeof_C_MStats)
 
        // Stack numbers are part of the heap numbers, separate those out for user consumption