const (
// Constants that we use and will transfer to the runtime.
+ minHeapAlign = 8
maxSmallSize = 32 << 10
smallSizeDiv = 8
smallSizeMax = 1024
classes = append(classes, class{}) // class #0 is a dummy entry
- align := 8
+ align := minHeapAlign
for size := align; size <= maxSmallSize; size += align {
if powerOfTwo(size) { // bump alignment once in a while
if size >= 2048 {
func printClasses(w io.Writer, classes []class) {
fmt.Fprintln(w, "const (")
+ fmt.Fprintf(w, "minHeapAlign = %d\n", minHeapAlign)
fmt.Fprintf(w, "_MaxSmallSize = %d\n", maxSmallSize)
fmt.Fprintf(w, "smallSizeDiv = %d\n", smallSizeDiv)
fmt.Fprintf(w, "smallSizeMax = %d\n", smallSizeMax)
"runtime/internal/sys"
)
+// Batch type values for the alloc/free experiment.
+const (
+ traceAllocFreeTypesBatch = iota // Contains types. [{id, address, size, ptrspan, name length, name string} ...]
+ traceAllocFreeInfoBatch // Contains info for interpreting events. [min heap addr, page size, min heap align, min stack align]
+)
+
// traceSnapshotMemory takes a snapshot of all runtime memory that there are events for
// (heap spans, heap objects, goroutine stacks, etc.) and writes out events for them.
//
// The world must be stopped and tracing must be enabled when this function is called.
-func traceSnapshotMemory() {
+func traceSnapshotMemory(gen uintptr) {
assertWorldStopped()
+ // Write a batch containing information that'll be necessary to
+ // interpret the events.
+ var flushed bool
+ w := unsafeTraceExpWriter(gen, nil, traceExperimentAllocFree)
+ w, flushed = w.ensure(1 + 4*traceBytesPerNumber)
+ if flushed {
+ // Annotate the batch as containing additional info.
+ w.byte(byte(traceAllocFreeInfoBatch))
+ }
+
+ // Emit info.
+ w.varint(uint64(trace.minPageHeapAddr))
+ w.varint(uint64(pageSize))
+ w.varint(uint64(minHeapAlign))
+ w.varint(uint64(fixedStack))
+
+ // Finish writing the batch.
+ w.flush().end()
+
// Start tracing.
trace := traceAcquire()
if !trace.ok() {
// traceHeapObjectID creates a trace ID for a heap object at address addr.
func traceHeapObjectID(addr uintptr) traceArg {
- return traceArg(uint64(addr)-trace.minPageHeapAddr) / 8
+ return traceArg(uint64(addr)-trace.minPageHeapAddr) / minHeapAlign
}
// GoroutineStackExists records that a goroutine stack already exists at address base with the provided size.
// bound is pretty loose, but avoids counting
// lots of varint sizes.
//
- // Add 1 because we might also write traceEvTypes.
- w, _ = w.ensure(1 + maxBytes)
+ // Add 1 because we might also write a traceAllocFreeTypesBatch byte.
+ var flushed bool
+ w, flushed = w.ensure(1 + maxBytes)
+ if flushed {
+ // Annotate the batch as containing types.
+ w.byte(byte(traceAllocFreeTypesBatch))
+ }
// Emit type.
w.varint(uint64(node.id))