import "runtime"
import "runtime/pprof"
func main() {
- _ = pprof.Profiles()
+ _ = pprof.Profiles()
+ println(runtime.MemProfileRate)
+}
+`,
+ "524288",
+ },
+ {
+ "with_memprofile_runtime_pprof_writeheap",
+ `
+package main
+import "io"
+import "runtime"
+import "runtime/pprof"
+func main() {
+ _ = pprof.WriteHeapProfile(io.Discard)
+ println(runtime.MemProfileRate)
+}
+`,
+ "524288",
+ },
+ {
+ "with_memprofile_runtime_pprof_lookupheap",
+ `
+package main
+import "runtime"
+import "runtime/pprof"
+func main() {
+ _ = pprof.Lookup("heap")
println(runtime.MemProfileRate)
}
`,
}
// Set runtime.disableMemoryProfiling bool if
- // runtime.MemProfile is not retained in the binary after
+ // runtime.memProfileInternal is not retained in the binary after
// deadcode (and we're not dynamically linking).
- memProfile := ctxt.loader.Lookup("runtime.MemProfile", abiInternalVer)
+ memProfile := ctxt.loader.Lookup("runtime.memProfileInternal", abiInternalVer)
if memProfile != 0 && !ctxt.loader.AttrReachable(memProfile) && !ctxt.DynlinkingGo() {
memProfSym := ctxt.loader.LookupOrCreateSym("runtime.disableMemoryProfiling", 0)
sb := ctxt.loader.MakeSymbolUpdater(memProfSym)
// at the beginning of main).
var MemProfileRate int = 512 * 1024
-// disableMemoryProfiling is set by the linker if runtime.MemProfile
+// disableMemoryProfiling is set by the linker if memory profiling
// is not used and the link type guarantees nobody else could use it
// elsewhere.
+// We check if the runtime.memProfileInternal symbol is present.
var disableMemoryProfiling bool
// A MemProfileRecord describes the live objects allocated
// memProfileInternal returns the number of records n in the profile. If there
// are less than size records, copyFn is invoked for each record, and ok returns
// true.
+//
+// The linker set disableMemoryProfiling to true to disable memory profiling
+// if this function is not reachable. Mark it noinline to ensure the symbol exists.
+// (This function is big and normally not inlined anyway.)
+// See also disableMemoryProfiling above and cmd/link/internal/ld/lib.go:linksetup.
+//
+//go:noinline
func memProfileInternal(size int, inuseZero bool, copyFn func(profilerecord.MemProfileRecord)) (n int, ok bool) {
cycle := mProfCycle.read()
// If we're between mProf_NextCycle and mProf_Flush, take care
runtime.ReadMemStats(memStats)
}
- // Find out how many records there are (MemProfile(nil, true)),
+ // Find out how many records there are (the call
+ // pprof_memProfileInternal(nil, true) below),
// allocate that many records, and get the data.
// There's a race—more records might be added between
// the two calls—so allocate a few extra records for safety