github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/bench/growslice/consts.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  package main
     6  
     7  const (
     8  	raceenabled = false
     9  	msanenabled = false
    10  	asanenabled = false
    11  
    12  	goarch_IsAmd64  = 1
    13  	goarch_IsArm64  = 0
    14  	goarch_IsMips   = 0
    15  	goarch_IsMipsle = 0
    16  	goarch_IsWasm   = 0
    17  	goarch_PtrSize  = 8
    18  
    19  	goos_IsAix     = 0
    20  	goos_IsIos     = 0
    21  	goos_IsPlan9   = 0
    22  	goos_IsWindows = 0
    23  
    24  	_ConcurrentSweep = 1
    25  )
    26  
    27  const (
    28  	maxTinySize   = _TinySize
    29  	tinySizeClass = _TinySizeClass
    30  	maxSmallSize  = _MaxSmallSize
    31  
    32  	pageShift = _PageShift
    33  	pageSize  = _PageSize
    34  
    35  	concurrentSweep = _ConcurrentSweep
    36  
    37  	_PageSize = 1 << _PageShift
    38  	_PageMask = _PageSize - 1
    39  
    40  	// _64bit = 1 on 64-bit systems, 0 on 32-bit systems
    41  	_64bit = 1 << (^uintptr(0) >> 63) / 2
    42  
    43  	// Tiny allocator parameters, see "Tiny allocator" comment in malloc.go.
    44  	_TinySize      = 16
    45  	_TinySizeClass = int8(2)
    46  
    47  	_FixAllocChunk = 16 << 10 // Chunk size for FixAlloc
    48  
    49  	// Per-P, per order stack segment cache size.
    50  	_StackCacheSize = 32 * 1024
    51  
    52  	// Number of orders that get caching. Order 0 is FixedStack
    53  	// and each successive order is twice as large.
    54  	// We want to cache 2KB, 4KB, 8KB, and 16KB stacks. Larger stacks
    55  	// will be allocated directly.
    56  	// Since FixedStack is different on different systems, we
    57  	// must vary NumStackOrders to keep the same maximum cached size.
    58  	//   OS               | FixedStack | NumStackOrders
    59  	//   -----------------+------------+---------------
    60  	//   linux/darwin/bsd | 2KB        | 4
    61  	//   windows/32       | 4KB        | 3
    62  	//   windows/64       | 8KB        | 2
    63  	//   plan9            | 4KB        | 3
    64  	_NumStackOrders = 4 - goarch_PtrSize/4*goos_IsWindows - 1*goos_IsPlan9
    65  
    66  	// heapAddrBits is the number of bits in a heap address. On
    67  	// amd64, addresses are sign-extended beyond heapAddrBits. On
    68  	// other arches, they are zero-extended.
    69  	//
    70  	// On most 64-bit platforms, we limit this to 48 bits based on a
    71  	// combination of hardware and OS limitations.
    72  	//
    73  	// amd64 hardware limits addresses to 48 bits, sign-extended
    74  	// to 64 bits. Addresses where the top 16 bits are not either
    75  	// all 0 or all 1 are "non-canonical" and invalid. Because of
    76  	// these "negative" addresses, we offset addresses by 1<<47
    77  	// (arenaBaseOffset) on amd64 before computing indexes into
    78  	// the heap arenas index. In 2017, amd64 hardware added
    79  	// support for 57 bit addresses; however, currently only Linux
    80  	// supports this extension and the kernel will never choose an
    81  	// address above 1<<47 unless mmap is called with a hint
    82  	// address above 1<<47 (which we never do).
    83  	//
    84  	// arm64 hardware (as of ARMv8) limits user addresses to 48
    85  	// bits, in the range [0, 1<<48).
    86  	//
    87  	// ppc64, mips64, and s390x support arbitrary 64 bit addresses
    88  	// in hardware. On Linux, Go leans on stricter OS limits. Based
    89  	// on Linux's processor.h, the user address space is limited as
    90  	// follows on 64-bit architectures:
    91  	//
    92  	// Architecture  Name              Maximum Value (exclusive)
    93  	// ---------------------------------------------------------------------
    94  	// amd64         TASK_SIZE_MAX     0x007ffffffff000 (47 bit addresses)
    95  	// arm64         TASK_SIZE_64      0x01000000000000 (48 bit addresses)
    96  	// ppc64{,le}    TASK_SIZE_USER64  0x00400000000000 (46 bit addresses)
    97  	// mips64{,le}   TASK_SIZE64       0x00010000000000 (40 bit addresses)
    98  	// s390x         TASK_SIZE         1<<64 (64 bit addresses)
    99  	//
   100  	// These limits may increase over time, but are currently at
   101  	// most 48 bits except on s390x. On all architectures, Linux
   102  	// starts placing mmap'd regions at addresses that are
   103  	// significantly below 48 bits, so even if it's possible to
   104  	// exceed Go's 48 bit limit, it's extremely unlikely in
   105  	// practice.
   106  	//
   107  	// On 32-bit platforms, we accept the full 32-bit address
   108  	// space because doing so is cheap.
   109  	// mips32 only has access to the low 2GB of virtual memory, so
   110  	// we further limit it to 31 bits.
   111  	//
   112  	// On ios/arm64, although 64-bit pointers are presumably
   113  	// available, pointers are truncated to 33 bits in iOS <14.
   114  	// Furthermore, only the top 4 GiB of the address space are
   115  	// actually available to the application. In iOS >=14, more
   116  	// of the address space is available, and the OS can now
   117  	// provide addresses outside of those 33 bits. Pick 40 bits
   118  	// as a reasonable balance between address space usage by the
   119  	// page allocator, and flexibility for what mmap'd regions
   120  	// we'll accept for the heap. We can't just move to the full
   121  	// 48 bits because this uses too much address space for older
   122  	// iOS versions.
   123  	// TODO(mknyszek): Once iOS <14 is deprecated, promote ios/arm64
   124  	// to a 48-bit address space like every other arm64 platform.
   125  	//
   126  	// WebAssembly currently has a limit of 4GB linear memory.
   127  	heapAddrBits = (_64bit*(1-goarch_IsWasm)*(1-goos_IsIos*goarch_IsArm64))*48 + (1-_64bit+goarch_IsWasm)*(32-(goarch_IsMips+goarch_IsMipsle)) + 40*goos_IsIos*goarch_IsArm64
   128  
   129  	// maxAlloc is the maximum size of an allocation. On 64-bit,
   130  	// it's theoretically possible to allocate 1<<heapAddrBits bytes. On
   131  	// 32-bit, however, this is one less than 1<<32 because the
   132  	// number of bytes in the address space doesn't actually fit
   133  	// in a uintptr.
   134  	maxAlloc = (1 << heapAddrBits) - (1-_64bit)*1
   135  
   136  	// The number of bits in a heap address, the size of heap
   137  	// arenas, and the L1 and L2 arena map sizes are related by
   138  	//
   139  	//   (1 << addr bits) = arena size * L1 entries * L2 entries
   140  	//
   141  	// Currently, we balance these as follows:
   142  	//
   143  	//       Platform  Addr bits  Arena size  L1 entries   L2 entries
   144  	// --------------  ---------  ----------  ----------  -----------
   145  	//       */64-bit         48        64MB           1    4M (32MB)
   146  	// windows/64-bit         48         4MB          64    1M  (8MB)
   147  	//      ios/arm64         33         4MB           1  2048  (8KB)
   148  	//       */32-bit         32         4MB           1  1024  (4KB)
   149  	//     */mips(le)         31         4MB           1   512  (2KB)
   150  
   151  	// heapArenaBytes is the size of a heap arena. The heap
   152  	// consists of mappings of size heapArenaBytes, aligned to
   153  	// heapArenaBytes. The initial heap mapping is one arena.
   154  	//
   155  	// This is currently 64MB on 64-bit non-Windows and 4MB on
   156  	// 32-bit and on Windows. We use smaller arenas on Windows
   157  	// because all committed memory is charged to the process,
   158  	// even if it's not touched. Hence, for processes with small
   159  	// heaps, the mapped arena space needs to be commensurate.
   160  	// This is particularly important with the race detector,
   161  	// since it significantly amplifies the cost of committed
   162  	// memory.
   163  	heapArenaBytes = 1 << logHeapArenaBytes
   164  
   165  	heapArenaWords = heapArenaBytes / goarch_PtrSize
   166  
   167  	// logHeapArenaBytes is log_2 of heapArenaBytes. For clarity,
   168  	// prefer using heapArenaBytes where possible (we need the
   169  	// constant to compute some other constants).
   170  	logHeapArenaBytes = (6+20)*(_64bit*(1-goos_IsWindows)*(1-goarch_IsWasm)*(1-goos_IsIos*goarch_IsArm64)) + (2+20)*(_64bit*goos_IsWindows) + (2+20)*(1-_64bit) + (2+20)*goarch_IsWasm + (2+20)*goos_IsIos*goarch_IsArm64
   171  
   172  	// heapArenaBitmapWords is the size of each heap arena's bitmap in uintptrs.
   173  	heapArenaBitmapWords = heapArenaWords / (8 * goarch_PtrSize)
   174  
   175  	pagesPerArena = heapArenaBytes / pageSize
   176  
   177  	// arenaL1Bits is the number of bits of the arena number
   178  	// covered by the first level arena map.
   179  	//
   180  	// This number should be small, since the first level arena
   181  	// map requires PtrSize*(1<<arenaL1Bits) of space in the
   182  	// binary's BSS. It can be zero, in which case the first level
   183  	// index is effectively unused. There is a performance benefit
   184  	// to this, since the generated code can be more efficient,
   185  	// but comes at the cost of having a large L2 mapping.
   186  	//
   187  	// We use the L1 map on 64-bit Windows because the arena size
   188  	// is small, but the address space is still 48 bits, and
   189  	// there's a high cost to having a large L2.
   190  	arenaL1Bits = 6 * (_64bit * goos_IsWindows)
   191  
   192  	// arenaL2Bits is the number of bits of the arena number
   193  	// covered by the second level arena index.
   194  	//
   195  	// The size of each arena map allocation is proportional to
   196  	// 1<<arenaL2Bits, so it's important that this not be too
   197  	// large. 48 bits leads to 32MB arena index allocations, which
   198  	// is about the practical threshold.
   199  	arenaL2Bits = heapAddrBits - logHeapArenaBytes - arenaL1Bits
   200  
   201  	// arenaL1Shift is the number of bits to shift an arena frame
   202  	// number by to compute an index into the first level arena map.
   203  	arenaL1Shift = arenaL2Bits
   204  
   205  	// arenaBits is the total bits in a combined arena map index.
   206  	// This is split between the index into the L1 arena map and
   207  	// the L2 arena map.
   208  	arenaBits = arenaL1Bits + arenaL2Bits
   209  
   210  	// arenaBaseOffset is the pointer value that corresponds to
   211  	// index 0 in the heap arena map.
   212  	//
   213  	// On amd64, the address space is 48 bits, sign extended to 64
   214  	// bits. This offset lets us handle "negative" addresses (or
   215  	// high addresses if viewed as unsigned).
   216  	//
   217  	// On aix/ppc64, this offset allows to keep the heapAddrBits to
   218  	// 48. Otherwise, it would be 60 in order to handle mmap addresses
   219  	// (in range 0x0a00000000000000 - 0x0afffffffffffff). But in this
   220  	// case, the memory reserved in (s *pageAlloc).init for chunks
   221  	// is causing important slowdowns.
   222  	//
   223  	// On other platforms, the user address space is contiguous
   224  	// and starts at 0, so no offset is necessary.
   225  	arenaBaseOffset = 0xffff800000000000*goarch_IsAmd64 + 0x0a00000000000000*goos_IsAix
   226  	// A typed version of this constant that will make it into DWARF (for viewcore).
   227  	arenaBaseOffsetUintptr = uintptr(arenaBaseOffset)
   228  
   229  	// Max number of threads to run garbage collection.
   230  	// 2, 3, and 4 are all plausible maximums depending
   231  	// on the hardware details of the machine. The garbage
   232  	// collector scales well to 32 cpus.
   233  	_MaxGcproc = 32
   234  
   235  	// minLegalPointer is the smallest possible legal pointer.
   236  	// This is the smallest possible architectural page size,
   237  	// since we assume that the first page is never mapped.
   238  	//
   239  	// This should agree with minZeroPage in the compiler.
   240  	minLegalPointer uintptr = 4096
   241  
   242  	// minHeapForMetadataHugePages sets a threshold on when certain kinds of
   243  	// heap metadata, currently the arenas map L2 entries and page alloc bitmap
   244  	// mappings, are allowed to be backed by huge pages. If the heap goal ever
   245  	// exceeds this threshold, then huge pages are enabled.
   246  	//
   247  	// These numbers are chosen with the assumption that huge pages are on the
   248  	// order of a few MiB in size.
   249  	//
   250  	// The kind of metadata this applies to has a very low overhead when compared
   251  	// to address space used, but their constant overheads for small heaps would
   252  	// be very high if they were to be backed by huge pages (e.g. a few MiB makes
   253  	// a huge difference for an 8 MiB heap, but barely any difference for a 1 GiB
   254  	// heap). The benefit of huge pages is also not worth it for small heaps,
   255  	// because only a very, very small part of the metadata is used for small heaps.
   256  	//
   257  	// N.B. If the heap goal exceeds the threshold then shrinks to a very small size
   258  	// again, then huge pages will still be enabled for this mapping. The reason is that
   259  	// there's no point unless we're also returning the physical memory for these
   260  	// metadata mappings back to the OS. That would be quite complex to do in general
   261  	// as the heap is likely fragmented after a reduction in heap size.
   262  	minHeapForMetadataHugePages = 1 << 30
   263  )