Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions builder/sizes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ func TestBinarySize(t *testing.T) {
// This is a small number of very diverse targets that we want to test.
tests := []sizeTest{
// microcontrollers
{"hifive1b", "examples/echo", 4484, 280, 0, 2252},
{"microbit", "examples/serial", 2808, 388, 8, 2256},
{"wioterminal", "examples/pininterrupt", 6064, 1484, 116, 6816},
{"hifive1b", "examples/echo", 4560, 280, 0, 2268},
{"microbit", "examples/serial", 2868, 388, 8, 2272},
{"wioterminal", "examples/pininterrupt", 6104, 1484, 116, 6832},

// TODO: also check wasm. Right now this is difficult, because
// wasm binaries are run through wasm-opt and therefore the
Expand Down
12 changes: 10 additions & 2 deletions src/runtime/gc_blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,10 @@ var (
nextAlloc gcBlock // the next block that should be tried by the allocator
endBlock gcBlock // the block just past the end of the available space
gcTotalAlloc uint64 // total number of bytes allocated
gcTotalBlocks uint64 // total number of allocated blocks
gcMallocs uint64 // total number of allocations
gcFrees uint64 // total number of objects freed
gcFreedBlocks uint64 // total number of freed blocks
)

// zeroSizedAlloc is just a sentinel that gets returned when allocating 0 bytes.
Expand Down Expand Up @@ -285,6 +287,7 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
gcMallocs++

neededBlocks := (size + (bytesPerBlock - 1)) / bytesPerBlock
gcTotalBlocks += uint64(neededBlocks)

// Continue looping until a run of free blocks has been found that fits the
// requested size.
Expand Down Expand Up @@ -619,20 +622,21 @@ func markRoot(addr, root uintptr) {
// It returns how many bytes are free in the heap after the sweep.
func sweep() (freeBytes uintptr) {
freeCurrentObject := false
var freed uint64
for block := gcBlock(0); block < endBlock; block++ {
switch block.state() {
case blockStateHead:
// Unmarked head. Free it, including all tail blocks following it.
block.markFree()
freeCurrentObject = true
gcFrees++
freeBytes += bytesPerBlock
freed++
case blockStateTail:
if freeCurrentObject {
// This is a tail object following an unmarked head.
// Free it now.
block.markFree()
freeBytes += bytesPerBlock
freed++
}
case blockStateMark:
// This is a marked object. The next tail blocks must not be freed,
Expand All @@ -644,6 +648,8 @@ func sweep() (freeBytes uintptr) {
freeBytes += bytesPerBlock
}
}
gcFreedBlocks += freed
freeBytes += uintptr(freed) * bytesPerBlock
return
}

Expand Down Expand Up @@ -690,6 +696,8 @@ func ReadMemStats(m *MemStats) {
m.Mallocs = gcMallocs
m.Frees = gcFrees
m.Sys = uint64(heapEnd - heapStart)
m.HeapAlloc = (gcTotalBlocks - gcFreedBlocks) * uint64(bytesPerBlock)
m.Alloc = m.HeapAlloc
}

func SetFinalizer(obj interface{}, finalizer interface{}) {
Expand Down
18 changes: 18 additions & 0 deletions src/runtime/mstats.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ package runtime
type MemStats struct {
// General statistics.

// Alloc is bytes of allocated heap objects.
//
// This is the same as HeapAlloc (see below).
Alloc uint64

// Sys is the total bytes of memory obtained from the OS.
//
// Sys is the sum of the XSys fields below. Sys measures the
Expand All @@ -18,6 +23,19 @@ type MemStats struct {

// Heap memory statistics.

// 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, total.
//
// In TinyGo unlike upstream Go, we make no distinction between
Expand Down