Skip to content

proposal: runtime/debug: add GCStats field to track count of marked pointers during last GC #52692

@sumerc

Description

@sumerc

Hi,

I would like to propose an idea (with few questions). I am still learning internals of Go (especially GC subsystem) so I hope my mental model is correct and clear.

Think about following code:

type ss struct {
     x int
}

a = make([]ss, ntimes)
for i := 0; i < ntimes; i++ {
    a[i] = ss{x: s{}}
}

Now, if I change the x int to x *int in the above code, the GC total latency jumps from ~106usec to ~1.6ms, roughly ~10x more overhead. Now, it is due to the fact that now GC needs to mark the pointer field in the structure, IIUC.

I think I am not the only one faced this: https://blog.gopheracademy.com/advent-2018/avoid-gc-overhead-large-heaps/. When there are lots of pointers held in memory, the GC latency increases.

Now I understand that this kind behavior is completely natural. I am more looking for ways to anticipate this kind of behavior during implementation via some kind of counter for observability reasons. This behavior becomes somewhat more subtle(?) if for example x is a string (string itself holds an implicit pointer) or x ia struct that contains a pointer somewhere deep in its definition.

Let me propose an idea:

// run same code as above

runtime.GC()

gcs := new(debug.GCStats)
debug.ReadGCStats(gcs)
fmt.Printf("Last GC total marked pointers:%d\n", gcs.NumPointers)

This would give the programmer a deterministic way to benchmark and optimize for allocations if possible. The current approach I am using to debug this is: to manually invoke GC and calculate elapsed time. This is somewhat ok, but IMHO it would be better and more deterministic to have a simple counter. WDYT?

And one more unrelated question just for learning: why we don't have a field for total GC latency (like a wall time), IIUC we currently have PauseTotalwhich shows the duration for STW, but would not it be nice to see whole running
time(total latency)? Probably this is not possible given that it runs concurrently in different goroutines or maybe is not just necessary?

Thanks,

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions