Skip to content

Commit f503ebf

Browse files
committed
runtime: track the last allocated block to minimize heap scanning
1 parent 84b9ec3 commit f503ebf

File tree

1 file changed

+17
-2
lines changed

1 file changed

+17
-2
lines changed

src/runtime/gc_blocks.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ var (
5252
metadataStart unsafe.Pointer // pointer to the start of the heap metadata
5353
nextAlloc gcBlock // the next block that should be tried by the allocator
5454
endBlock gcBlock // the block just past the end of the available space
55+
maxBlock gcBlock // maximum block that has been allocated
5556
gcTotalAlloc uint64 // total number of bytes allocated
5657
gcTotalBlocks uint64 // total number of allocated blocks
5758
gcMallocs uint64 // total number of allocations
@@ -377,6 +378,9 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
377378
size -= add
378379
}
379380
memzero(pointer, size)
381+
if nextAlloc > maxBlock {
382+
maxBlock = nextAlloc - 1
383+
}
380384
return pointer
381385
}
382386
}
@@ -586,7 +590,7 @@ func finishMark() {
586590
for stackOverflow {
587591
// Re-mark all blocks.
588592
stackOverflow = false
589-
for block := gcBlock(0); block < endBlock; block++ {
593+
for block := gcBlock(0); block <= maxBlock; block++ {
590594
if block.state() != blockStateMark {
591595
// Block is not marked, so we do not need to rescan it.
592596
continue
@@ -621,9 +625,10 @@ func markRoot(addr, root uintptr) {
621625
// Sweep goes through all memory and frees unmarked memory.
622626
// It returns how many bytes are free in the heap after the sweep.
623627
func sweep() (freeBytes uintptr) {
628+
var lastBlock gcBlock
624629
freeCurrentObject := false
625630
var freed uint64
626-
for block := gcBlock(0); block < endBlock; block++ {
631+
for block := gcBlock(0); block <= maxBlock; block++ {
627632
switch block.state() {
628633
case blockStateHead:
629634
// Unmarked head. Free it, including all tail blocks following it.
@@ -637,19 +642,29 @@ func sweep() (freeBytes uintptr) {
637642
// Free it now.
638643
block.markFree()
639644
freed++
645+
freeBytes += bytesPerBlock
646+
} else {
647+
lastBlock = block
640648
}
641649
case blockStateMark:
642650
// This is a marked object. The next tail blocks must not be freed,
643651
// but the mark bit must be removed so the next GC cycle will
644652
// collect this object if it is unreferenced then.
645653
block.unmark()
646654
freeCurrentObject = false
655+
lastBlock = block
647656
case blockStateFree:
648657
freeBytes += bytesPerBlock
649658
}
650659
}
660+
651661
gcFreedBlocks += freed
652662
freeBytes += uintptr(freed) * bytesPerBlock
663+
664+
if gcAsserts && lastBlock > maxBlock {
665+
runtimePanic("gc: lastblock > maxBlock")
666+
}
667+
maxBlock = lastBlock
653668
return
654669
}
655670

0 commit comments

Comments
 (0)