Source File
mgcscavenge.go
Belonging Package
runtime
package runtime
import (
)
scavengePercent = 1 // 1%
retainExtraPercent = 10
scavengeCostRatio = 0.7 * (sys.GoosDarwin + sys.GoosIos)
scavengeReservationShards = 64
)
if memstats.last_next_gc == 0 {
mheap_.scavengeGoal = ^uint64(0)
return
= ( + uint64(physPageSize) - 1) &^ (uint64(physPageSize) - 1)
:= heapRetained()
if <= || - < uint64(physPageSize) {
mheap_.scavengeGoal = ^uint64(0)
return
}
mheap_.scavengeGoal =
}
func () {
atomic.Store(&scavenge.sysmonWake, 1)
}
atomic.Store(&scavenge.sysmonWake, 0)
:= nanotime()
resetTimer(scavenge.timer, +)
return nanotime() -
}
const = scavengePercent / 100.0
:= float64()
for {
:= uintptr(0)
:= float64(0)
systemstack(func() {
lock(&mheap_.lock)
, := heapRetained(), mheap_.scavengeGoal
if <= {
unlock(&mheap_.lock)
return
}
throw("released less than one physical page of memory")
}
const = 10e3
if <= 0 {
= * float64(/physPageSize)
}
*= 1 + scavengeCostRatio
const = 10e6
if > {
=
}
:= /
:= int64( * / (scavengePercent / 100.0))
:= scavengeSleep()
:= / ( + float64())
const = 1 / 1000
if < {
=
}
const = 0.5
= * + (1-)*
}
}
func ( *pageAlloc) ( uintptr, bool) uintptr {
assertLockHeld(.mheapLock)
var (
addrRange
uint32
)
:= uintptr(0)
for < {
if .size() == 0 {
if , = .scavengeReserve(); .size() == 0 {
break
}
}
, := .scavengeOne(, -, )
+=
=
.scavengeUnreserve(, )
return
}
func ( uint32, uintptr, bool) {
printlock()
print("scav ", , " ",
>>10, " KiB work, ",
atomic.Load64(&memstats.heap_released)>>10, " KiB total, ",
(atomic.Load64(&memstats.heap_inuse)*100)/heapRetained(), "% util",
)
if {
print(" (forced)")
}
println()
printunlock()
}
var offAddr
.scav.reservationBytes = alignUp(.inUse.totalBytes, pallocChunkBytes) / scavengeReservationShards
.scav.gen++
.scav.released = 0
.scav.freeHWM = minOffAddr
.scav.scavLWM = maxOffAddr
}
func ( *pageAlloc) () (addrRange, uint32) {
assertLockHeld(.mheapLock)
:= .scav.inUse.removeLast(.scav.reservationBytes)
:= alignDown(.base.addr(), pallocChunkBytes)
return 0,
if .base.addr()%pallocChunkBytes != 0 {
throw("scavengeOne called with unaligned work region")
:= physPageSize / pageSize
if < 1 {
= 1
}
:= .limit.addr() - 1
:= chunkIndex()
, := .chunkOf().findScavengeCandidate(chunkPageIndex(), , )
if != 0 {
.limit = offAddr{.scavengeRangeLocked(, , )}
assertLockHeld(.mheapLock) // Must be locked on return.
return uintptr() * pageSize,
}
:= (*[1 << pallocChunksL2Bits]pallocData)(atomic.Loadp(unsafe.Pointer(&.chunks[.l1()])))
if != nil && [.l2()].hasScavengeCandidate() {
return , true
}
}
return 0, false
}
for .size() != 0 {
()
, := ()
()
:= .chunkOf()
, := .findScavengeCandidate(pallocChunkPages-1, , )
if > 0 {
.limit = offAddr{.scavengeRangeLocked(, , )}
assertLockHeld(.mheapLock) // Must be locked on return.
return uintptr() * pageSize,
}
.limit = offAddr{chunkBase()}
}
assertLockHeld(.mheapLock) // Must be locked on return.
return 0,
}
return ^(((( & ) + ) | ) | )
switch {
case 1:
return
case 2:
= (, 0x5555555555555555)
case 4:
= (, 0x7777777777777777)
case 8:
= (, 0x7f7f7f7f7f7f7f7f)
case 16:
= (, 0x7fff7fff7fff7fff)
case 32:
= (, 0x7fffffff7fffffff)
case 64: // == maxPagesPerPhysPage
= (, 0x7fffffffffffffff)
default:
throw("bad m value")
return ^(( - ( >> ( - 1))) | )
}
func ( *pallocData) ( uintptr) bool {
if &(-1) != 0 || == 0 {
print("runtime: min = ", , "\n")
throw("min must be a non-zero power of 2")
} else if > maxPagesPerPhysPage {
print("runtime: min = ", , "\n")
throw("min too large")
}
:= fillAligned(.scavenged[]|.pallocBits[], uint())
func ( *pallocData) ( uint, , uintptr) (uint, uint) {
if &(-1) != 0 || == 0 {
print("runtime: min = ", , "\n")
throw("min must be a non-zero power of 2")
} else if > maxPagesPerPhysPage {
print("runtime: min = ", , "\n")
throw("min too large")
if == 0 {
=
} else {
= alignUp(, )
}
:= fillAligned(.scavenged[]|.pallocBits[], uint())
if != ^uint64(0) {
break
}
}
return 0, 0
:= fillAligned(.scavenged[]|.pallocBits[], uint())
:= uint(sys.LeadingZeros64(^))
, := uint(0), uint()*64+(64-)
= uint(sys.LeadingZeros64( << ))
= 64 -
for := - 1; >= 0; -- {
:= fillAligned(.scavenged[]|.pallocBits[], uint())
+= uint(sys.LeadingZeros64())
break
}
}
}
= + ( - )
=
}
}
}
return ,
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |