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 )