From 842c906e2e9560187d4877d9f52e8f9ceb63d84c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Oudompheng?= Date: Mon, 6 Feb 2012 19:16:26 +0100 Subject: [PATCH] runtime: delete UpdateMemStats, replace with ReadMemStats(&stats). Unexports runtime.MemStats and rename MemStatsType to MemStats. The new accessor requires passing a pointer to a user-allocated MemStats structure. Fixes #2572. R=bradfitz, rsc, bradfitz, gustavo CC=golang-dev, remy https://golang.org/cl/5616072 --- src/cmd/godoc/godoc.go | 7 +++++-- src/pkg/encoding/gob/timing_test.go | 18 ++++++++++-------- src/pkg/expvar/expvar.go | 4 +++- src/pkg/fmt/fmt_test.go | 9 +++++---- src/pkg/net/rpc/server_test.go | 9 +++++---- src/pkg/reflect/all_test.go | 10 +++++++--- src/pkg/runtime/gc_test.go | 11 ++++++----- src/pkg/runtime/malloc.h | 2 +- src/pkg/runtime/mem.go | 21 ++++++++------------- src/pkg/runtime/mgc0.c | 3 ++- src/pkg/runtime/pprof/pprof.go | 3 ++- src/pkg/strconv/itoa_test.go | 9 +++++---- test/bench/garbage/parser.go | 20 ++++++++++---------- test/bench/garbage/stats.go | 3 ++- test/bench/garbage/tree2.go | 15 ++++++++------- test/chan/select2.go | 9 ++++++--- test/closure.go | 11 ++++++----- test/gc2.go | 8 +++++--- test/init1.go | 14 +++++++------- test/malloc1.go | 5 +++-- test/mallocrand.go | 5 +++-- test/mallocrep.go | 24 +++++++++++++----------- test/mallocrep1.go | 14 +++++++------- 23 files changed, 129 insertions(+), 105 deletions(-) diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go index 34e058ab5c1..5745b28ba69 100644 --- a/src/cmd/godoc/godoc.go +++ b/src/cmd/godoc/godoc.go @@ -1510,9 +1510,12 @@ func updateIndex() { log.Printf("index updated (%gs, %d bytes of source, %d files, %d lines, %d unique words, %d spots)", secs, stats.Bytes, stats.Files, stats.Lines, stats.Words, stats.Spots) } - log.Printf("before GC: bytes = %d footprint = %d", runtime.MemStats.HeapAlloc, runtime.MemStats.Sys) + memstats := new(runtime.MemStats) + runtime.ReadMemStats(memstats) + log.Printf("before GC: bytes = %d footprint = %d", memstats.HeapAlloc, memstats.Sys) runtime.GC() - log.Printf("after GC: bytes = %d footprint = %d", runtime.MemStats.HeapAlloc, runtime.MemStats.Sys) + runtime.ReadMemStats(memstats) + log.Printf("after GC: bytes = %d footprint = %d", memstats.HeapAlloc, memstats.Sys) } func indexer() { diff --git a/src/pkg/encoding/gob/timing_test.go b/src/pkg/encoding/gob/timing_test.go index 1017eb7f51d..b9371c42309 100644 --- a/src/pkg/encoding/gob/timing_test.go +++ b/src/pkg/encoding/gob/timing_test.go @@ -53,8 +53,9 @@ func TestCountEncodeMallocs(t *testing.T) { var buf bytes.Buffer enc := NewEncoder(&buf) bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")} - runtime.UpdateMemStats() - mallocs := 0 - runtime.MemStats.Mallocs + memstats := new(runtime.MemStats) + runtime.ReadMemStats(memstats) + mallocs := 0 - memstats.Mallocs const count = 1000 for i := 0; i < count; i++ { err := enc.Encode(bench) @@ -62,8 +63,8 @@ func TestCountEncodeMallocs(t *testing.T) { t.Fatal("encode:", err) } } - runtime.UpdateMemStats() - mallocs += runtime.MemStats.Mallocs + runtime.ReadMemStats(memstats) + mallocs += memstats.Mallocs fmt.Printf("mallocs per encode of type Bench: %d\n", mallocs/count) } @@ -79,8 +80,9 @@ func TestCountDecodeMallocs(t *testing.T) { } } dec := NewDecoder(&buf) - runtime.UpdateMemStats() - mallocs := 0 - runtime.MemStats.Mallocs + memstats := new(runtime.MemStats) + runtime.ReadMemStats(memstats) + mallocs := 0 - memstats.Mallocs for i := 0; i < count; i++ { *bench = Bench{} err := dec.Decode(&bench) @@ -88,7 +90,7 @@ func TestCountDecodeMallocs(t *testing.T) { t.Fatal("decode:", err) } } - runtime.UpdateMemStats() - mallocs += runtime.MemStats.Mallocs + runtime.ReadMemStats(memstats) + mallocs += memstats.Mallocs fmt.Printf("mallocs per decode of type Bench: %d\n", mallocs/count) } diff --git a/src/pkg/expvar/expvar.go b/src/pkg/expvar/expvar.go index ee32eff9ea3..0ccfb34328d 100644 --- a/src/pkg/expvar/expvar.go +++ b/src/pkg/expvar/expvar.go @@ -277,7 +277,9 @@ func cmdline() interface{} { } func memstats() interface{} { - return runtime.MemStats + stats := new(runtime.MemStats) + runtime.ReadMemStats(stats) + return *stats } func init() { diff --git a/src/pkg/fmt/fmt_test.go b/src/pkg/fmt/fmt_test.go index cd0b0ce66be..44dcae46ced 100644 --- a/src/pkg/fmt/fmt_test.go +++ b/src/pkg/fmt/fmt_test.go @@ -538,13 +538,14 @@ var _ bytes.Buffer func TestCountMallocs(t *testing.T) { for _, mt := range mallocTest { const N = 100 - runtime.UpdateMemStats() - mallocs := 0 - runtime.MemStats.Mallocs + memstats := new(runtime.MemStats) + runtime.ReadMemStats(memstats) + mallocs := 0 - memstats.Mallocs for i := 0; i < N; i++ { mt.fn() } - runtime.UpdateMemStats() - mallocs += runtime.MemStats.Mallocs + runtime.ReadMemStats(memstats) + mallocs += memstats.Mallocs if mallocs/N > uint64(mt.count) { t.Errorf("%s: expected %d mallocs, got %d", mt.desc, mt.count, mallocs/N) } diff --git a/src/pkg/net/rpc/server_test.go b/src/pkg/net/rpc/server_test.go index b05c63c0563..8cfa033ccc3 100644 --- a/src/pkg/net/rpc/server_test.go +++ b/src/pkg/net/rpc/server_test.go @@ -442,8 +442,9 @@ func countMallocs(dial func() (*Client, error), t *testing.T) uint64 { } args := &Args{7, 8} reply := new(Reply) - runtime.UpdateMemStats() - mallocs := 0 - runtime.MemStats.Mallocs + memstats := new(runtime.MemStats) + runtime.ReadMemStats(memstats) + mallocs := 0 - memstats.Mallocs const count = 100 for i := 0; i < count; i++ { err := client.Call("Arith.Add", args, reply) @@ -454,8 +455,8 @@ func countMallocs(dial func() (*Client, error), t *testing.T) uint64 { t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B) } } - runtime.UpdateMemStats() - mallocs += runtime.MemStats.Mallocs + runtime.ReadMemStats(memstats) + mallocs += memstats.Mallocs return mallocs / count } diff --git a/src/pkg/reflect/all_test.go b/src/pkg/reflect/all_test.go index 8ae977912b3..ad995875537 100644 --- a/src/pkg/reflect/all_test.go +++ b/src/pkg/reflect/all_test.go @@ -1545,15 +1545,19 @@ func TestAddr(t *testing.T) { func noAlloc(t *testing.T, n int, f func(int)) { // once to prime everything f(-1) - runtime.MemStats.Mallocs = 0 + memstats := new(runtime.MemStats) + runtime.ReadMemStats(memstats) + oldmallocs := memstats.Mallocs for j := 0; j < n; j++ { f(j) } // A few allocs may happen in the testing package when GOMAXPROCS > 1, so don't // require zero mallocs. - if runtime.MemStats.Mallocs > 5 { - t.Fatalf("%d mallocs after %d iterations", runtime.MemStats.Mallocs, n) + runtime.ReadMemStats(memstats) + mallocs := memstats.Mallocs - oldmallocs + if mallocs > 5 { + t.Fatalf("%d mallocs after %d iterations", mallocs, n) } } diff --git a/src/pkg/runtime/gc_test.go b/src/pkg/runtime/gc_test.go index 00b3a04ce9d..739ebcba2ff 100644 --- a/src/pkg/runtime/gc_test.go +++ b/src/pkg/runtime/gc_test.go @@ -10,20 +10,21 @@ import ( ) func TestGcSys(t *testing.T) { + memstats := new(runtime.MemStats) runtime.GC() - runtime.UpdateMemStats() - sys := runtime.MemStats.Sys + runtime.ReadMemStats(memstats) + sys := memstats.Sys for i := 0; i < 1000000; i++ { workthegc() } // Should only be using a few MB. - runtime.UpdateMemStats() - if sys > runtime.MemStats.Sys { + runtime.ReadMemStats(memstats) + if sys > memstats.Sys { sys = 0 } else { - sys = runtime.MemStats.Sys - sys + sys = memstats.Sys - sys } t.Logf("used %d extra bytes", sys) if sys > 4<<20 { diff --git a/src/pkg/runtime/malloc.h b/src/pkg/runtime/malloc.h index a85e1af8c70..d79c86d1244 100644 --- a/src/pkg/runtime/malloc.h +++ b/src/pkg/runtime/malloc.h @@ -234,7 +234,7 @@ struct MStats } by_size[NumSizeClasses]; }; -#define mstats runtime·MemStats /* name shared with Go */ +#define mstats runtime·memStats /* name shared with Go */ extern MStats mstats; diff --git a/src/pkg/runtime/mem.go b/src/pkg/runtime/mem.go index 93d155a7f82..3ad906ac276 100644 --- a/src/pkg/runtime/mem.go +++ b/src/pkg/runtime/mem.go @@ -6,9 +6,9 @@ package runtime import "unsafe" -type MemStatsType struct { +// A MemStats records statistics about the memory allocator. +type MemStats struct { // General statistics. - // Not locked during update; approximate. Alloc uint64 // bytes allocated and still in use TotalAlloc uint64 // bytes allocated (even if freed) Sys uint64 // bytes obtained from system (should be sum of XxxSys below) @@ -43,7 +43,6 @@ type MemStatsType struct { DebugGC bool // Per-size allocation statistics. - // Not locked during update; approximate. // 61 is NumSizeClasses in the C code. BySize [61]struct { Size uint32 @@ -54,21 +53,17 @@ type MemStatsType struct { var sizeof_C_MStats uintptr // filled in by malloc.goc +var memStats MemStats + func init() { - if sizeof_C_MStats != unsafe.Sizeof(MemStats) { - println(sizeof_C_MStats, unsafe.Sizeof(MemStats)) + if sizeof_C_MStats != unsafe.Sizeof(memStats) { + println(sizeof_C_MStats, unsafe.Sizeof(memStats)) panic("MStats vs MemStatsType size mismatch") } } -// MemStats holds statistics about the memory system. -// The statistics may be out of date, as the information is -// updated lazily from per-thread caches. -// Use UpdateMemStats to bring the statistics up to date. -var MemStats MemStatsType - -// UpdateMemStats brings MemStats up to date. -func UpdateMemStats() +// ReadMemStats populates m with memory allocator statistics. +func ReadMemStats(m *MemStats) // GC runs a garbage collection. func GC() diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c index 78daa783621..1b959286ac3 100644 --- a/src/pkg/runtime/mgc0.c +++ b/src/pkg/runtime/mgc0.c @@ -997,7 +997,7 @@ runtime·gc(int32 force) } void -runtime·UpdateMemStats(void) +runtime·ReadMemStats(MStats *stats) { // Have to acquire gcsema to stop the world, // because stoptheworld can only be used by @@ -1007,6 +1007,7 @@ runtime·UpdateMemStats(void) m->gcing = 1; runtime·stoptheworld(); cachestats(); + *stats = mstats; m->gcing = 0; runtime·semrelease(&gcsema); runtime·starttheworld(false); diff --git a/src/pkg/runtime/pprof/pprof.go b/src/pkg/runtime/pprof/pprof.go index d14bb141c4a..a8e78e0ea75 100644 --- a/src/pkg/runtime/pprof/pprof.go +++ b/src/pkg/runtime/pprof/pprof.go @@ -75,7 +75,8 @@ func WriteHeapProfile(w io.Writer) error { // Print memstats information too. // Pprof will ignore, but useful for people. - s := &runtime.MemStats + s := new(runtime.MemStats) + runtime.ReadMemStats(s) fmt.Fprintf(b, "\n# runtime.MemStats\n") fmt.Fprintf(b, "# Alloc = %d\n", s.Alloc) fmt.Fprintf(b, "# TotalAlloc = %d\n", s.TotalAlloc) diff --git a/src/pkg/strconv/itoa_test.go b/src/pkg/strconv/itoa_test.go index d4b09a5d87d..6687314d2f6 100644 --- a/src/pkg/strconv/itoa_test.go +++ b/src/pkg/strconv/itoa_test.go @@ -127,11 +127,12 @@ func TestUitoa(t *testing.T) { } func numAllocations(f func()) int { - runtime.UpdateMemStats() - n0 := runtime.MemStats.Mallocs + memstats := new(runtime.MemStats) + runtime.ReadMemStats(memstats) + n0 := memstats.Mallocs f() - runtime.UpdateMemStats() - return int(runtime.MemStats.Mallocs - n0) + runtime.ReadMemStats(memstats) + return int(memstats.Mallocs - n0) } var globalBuf [64]byte diff --git a/test/bench/garbage/parser.go b/test/bench/garbage/parser.go index 9e15f6c0f4d..d66281b6bf4 100644 --- a/test/bench/garbage/parser.go +++ b/test/bench/garbage/parser.go @@ -73,7 +73,7 @@ func parseDir(dirpath string) map[string]*ast.Package { } func main() { - st := &runtime.MemStats + st := new(runtime.MemStats) packages = append(packages, packages...) packages = append(packages, packages...) n := flag.Int("n", 4, "iterations") @@ -83,14 +83,17 @@ func main() { var lastParsed []map[string]*ast.Package var t0 time.Time + var numGC uint32 + var pauseTotalNs uint64 pkgroot := runtime.GOROOT() + "/src/pkg/" for pass := 0; pass < 2; pass++ { // Once the heap is grown to full size, reset counters. // This hides the start-up pauses, which are much smaller // than the normal pauses and would otherwise make // the average look much better than it actually is. - st.NumGC = 0 - st.PauseTotalNs = 0 + runtime.ReadMemStats(st) + numGC = st.NumGC + pauseTotalNs = st.PauseTotalNs t0 = time.Now() for i := 0; i < *n; i++ { @@ -107,6 +110,9 @@ func main() { } t1 := time.Now() + runtime.ReadMemStats(st) + st.NumGC -= numGC + st.PauseTotalNs -= pauseTotalNs fmt.Printf("Alloc=%d/%d Heap=%d Mallocs=%d PauseTime=%.3f/%d = %.3f\n", st.Alloc, st.TotalAlloc, st.Sys, @@ -142,9 +148,7 @@ var packages = []string{ "container/list", "container/ring", "crypto/aes", - "crypto/blowfish", "crypto/hmac", - "crypto/md4", "crypto/md5", "crypto/rand", "crypto/rc4", @@ -155,7 +159,6 @@ var packages = []string{ "crypto/subtle", "crypto/tls", "crypto/x509", - "crypto/xtea", "debug/dwarf", "debug/macho", "debug/elf", @@ -164,7 +167,6 @@ var packages = []string{ "encoding/ascii85", "encoding/base64", "encoding/binary", - "encoding/git85", "encoding/hex", "encoding/pem", "os/exec", @@ -193,8 +195,7 @@ var packages = []string{ "mime", "net", "os", - "os/signal", - "patch", + "exp/signal", "path", "math/rand", "reflect", @@ -219,6 +220,5 @@ var packages = []string{ "unicode", "unicode/utf8", "unicode/utf16", - "websocket", "encoding/xml", } diff --git a/test/bench/garbage/stats.go b/test/bench/garbage/stats.go index 985e7eaf5dc..cdcb32f9b65 100644 --- a/test/bench/garbage/stats.go +++ b/test/bench/garbage/stats.go @@ -12,7 +12,8 @@ import ( ) func gcstats(name string, n int, t time.Duration) { - st := &runtime.MemStats + st := new(runtime.MemStats) + runtime.ReadMemStats(st) fmt.Printf("garbage.%sMem Alloc=%d/%d Heap=%d NextGC=%d Mallocs=%d\n", name, st.Alloc, st.TotalAlloc, st.Sys, st.NextGC, st.Mallocs) fmt.Printf("garbage.%s %d %d ns/op\n", name, n, t.Nanoseconds()/int64(n)) fmt.Printf("garbage.%sLastPause 1 %d ns/op\n", name, st.PauseNs[(st.NumGC-1)%uint32(len(st.PauseNs))]) diff --git a/test/bench/garbage/tree2.go b/test/bench/garbage/tree2.go index 6d78f72c5b8..3db0a0ba3c3 100644 --- a/test/bench/garbage/tree2.go +++ b/test/bench/garbage/tree2.go @@ -30,6 +30,7 @@ var ( heap *Object calls [20]int numobjects int64 + memstats runtime.MemStats ) func buildHeap() { @@ -55,10 +56,10 @@ func buildTree(objsize, size float64, depth int) (*Object, float64) { func gc() { runtime.GC() - runtime.UpdateMemStats() - pause := runtime.MemStats.PauseTotalNs - inuse := runtime.MemStats.Alloc - free := runtime.MemStats.TotalAlloc - inuse + runtime.ReadMemStats(&memstats) + pause := memstats.PauseTotalNs + inuse := memstats.Alloc + free := memstats.TotalAlloc - inuse fmt.Printf("gc pause: %8.3f ms; collect: %8.0f MB; heapsize: %8.0f MB\n", float64(pause-lastPauseNs)/1e6, float64(free-lastFree)/1048576, @@ -71,9 +72,9 @@ func main() { flag.Parse() buildHeap() runtime.GOMAXPROCS(*cpus) - runtime.UpdateMemStats() - lastPauseNs = runtime.MemStats.PauseTotalNs - lastFree = runtime.MemStats.TotalAlloc - runtime.MemStats.Alloc + runtime.ReadMemStats(&memstats) + lastPauseNs = memstats.PauseTotalNs + lastFree = memstats.TotalAlloc - memstats.Alloc if *cpuprofile != "" { f, err := os.Create(*cpuprofile) if err != nil { diff --git a/test/chan/select2.go b/test/chan/select2.go index e24c51ed16c..2cbb86ec626 100644 --- a/test/chan/select2.go +++ b/test/chan/select2.go @@ -35,14 +35,17 @@ func main() { go sender(c, 100000) receiver(c, dummy, 100000) runtime.GC() - runtime.MemStats.Alloc = 0 + memstats := new(runtime.MemStats) + runtime.ReadMemStats(memstats) + alloc := memstats.Alloc // second time shouldn't increase footprint by much go sender(c, 100000) receiver(c, dummy, 100000) runtime.GC() + runtime.ReadMemStats(memstats) - if runtime.MemStats.Alloc > 1e5 { - println("BUG: too much memory for 100,000 selects:", runtime.MemStats.Alloc) + if memstats.Alloc-alloc > 1e5 { + println("BUG: too much memory for 100,000 selects:", memstats.Alloc-alloc) } } diff --git a/test/closure.go b/test/closure.go index 97da1dd2304..c2248d68e95 100644 --- a/test/closure.go +++ b/test/closure.go @@ -92,8 +92,9 @@ func main() { go h() check([]int{100, 200, 101, 201, 500, 101, 201, 500}) - runtime.UpdateMemStats() - n0 := runtime.MemStats.Mallocs + memstats := new(runtime.MemStats) + runtime.ReadMemStats(memstats) + n0 := memstats.Mallocs x, y := newfunc(), newfunc() if x(1) != 1 || y(2) != 2 { @@ -101,8 +102,8 @@ func main() { fail = true } - runtime.UpdateMemStats() - if n0 != runtime.MemStats.Mallocs { + runtime.ReadMemStats(memstats) + if n0 != memstats.Mallocs { println("newfunc allocated unexpectedly") fail = true } @@ -110,7 +111,7 @@ func main() { ff(1) if fail { - panic("fail") + panic("fail") } } diff --git a/test/gc2.go b/test/gc2.go index c54d807df72..772f9810daa 100644 --- a/test/gc2.go +++ b/test/gc2.go @@ -19,7 +19,9 @@ import ( func main() { const N = 10000 - st := runtime.MemStats + st := new(runtime.MemStats) + memstats := new(runtime.MemStats) + runtime.ReadMemStats(st) for i := 0; i < N; i++ { c := make(chan int, 10) _ = c @@ -33,8 +35,8 @@ func main() { } } - runtime.UpdateMemStats() - obj := runtime.MemStats.HeapObjects - st.HeapObjects + runtime.ReadMemStats(memstats) + obj := memstats.HeapObjects - st.HeapObjects if obj > N/5 { fmt.Println("too many objects left:", obj) os.Exit(1) diff --git a/test/init1.go b/test/init1.go index 9ce3c12ee68..56ef17249fd 100644 --- a/test/init1.go +++ b/test/init1.go @@ -16,10 +16,11 @@ func init() { c := make(chan int) go send(c) <-c - - const chunk = 1<<20 - runtime.UpdateMemStats() - sys := runtime.MemStats.Sys + + const chunk = 1 << 20 + memstats := new(runtime.MemStats) + runtime.ReadMemStats(memstats) + sys := memstats.Sys b := make([]byte, chunk) for i := range b { b[i] = byte(i%10 + '0') @@ -28,8 +29,8 @@ func init() { for i := 0; i < 1000; i++ { x = []byte(s) } - runtime.UpdateMemStats() - sys1 := runtime.MemStats.Sys + runtime.ReadMemStats(memstats) + sys1 := memstats.Sys if sys1-sys > chunk*50 { println("allocated 1000 chunks of", chunk, "and used ", sys1-sys, "memory") } @@ -41,4 +42,3 @@ func send(c chan int) { func main() { } - diff --git a/test/malloc1.go b/test/malloc1.go index 61f1797c75d..0f7f0b267a0 100644 --- a/test/malloc1.go +++ b/test/malloc1.go @@ -17,9 +17,10 @@ import ( var chatty = flag.Bool("v", false, "chatty") func main() { + memstats := new(runtime.MemStats) runtime.Free(runtime.Alloc(1)) - runtime.UpdateMemStats() + runtime.ReadMemStats(memstats) if *chatty { - fmt.Printf("%+v %v\n", runtime.MemStats, uint64(0)) + fmt.Printf("%+v %v\n", memstats, uint64(0)) } } diff --git a/test/mallocrand.go b/test/mallocrand.go index 726e36799a8..69d07cec5d2 100644 --- a/test/mallocrand.go +++ b/test/mallocrand.go @@ -21,8 +21,9 @@ var footprint uint64 var allocated uint64 func bigger() { - runtime.UpdateMemStats() - if f := runtime.MemStats.Sys; footprint < f { + memstats := new(runtime.MemStats) + runtime.ReadMemStats(memstats) + if f := memstats.Sys; footprint < f { footprint = f if *chatty { println("Footprint", footprint, " for ", allocated) diff --git a/test/mallocrep.go b/test/mallocrep.go index cffcd1638fc..4188da9b833 100644 --- a/test/mallocrep.go +++ b/test/mallocrep.go @@ -16,10 +16,12 @@ import ( var chatty = flag.Bool("v", false, "chatty") var oldsys uint64 +var memstats runtime.MemStats func bigger() { - runtime.UpdateMemStats() - if st := runtime.MemStats; oldsys < st.Sys { + st := &memstats + runtime.ReadMemStats(st) + if oldsys < st.Sys { oldsys = st.Sys if *chatty { println(st.Sys, " system bytes for ", st.Alloc, " Go bytes") @@ -32,26 +34,26 @@ func bigger() { } func main() { - runtime.GC() // clean up garbage from init - runtime.UpdateMemStats() // first call can do some allocations - runtime.MemProfileRate = 0 // disable profiler - runtime.MemStats.Alloc = 0 // ignore stacks + runtime.GC() // clean up garbage from init + runtime.ReadMemStats(&memstats) // first call can do some allocations + runtime.MemProfileRate = 0 // disable profiler + stacks := memstats.Alloc // ignore stacks flag.Parse() for i := 0; i < 1<<7; i++ { for j := 1; j <= 1<<22; j <<= 1 { if i == 0 && *chatty { println("First alloc:", j) } - if a := runtime.MemStats.Alloc; a != 0 { + if a := memstats.Alloc - stacks; a != 0 { println("no allocations but stats report", a, "bytes allocated") panic("fail") } b := runtime.Alloc(uintptr(j)) - runtime.UpdateMemStats() - during := runtime.MemStats.Alloc + runtime.ReadMemStats(&memstats) + during := memstats.Alloc - stacks runtime.Free(b) - runtime.UpdateMemStats() - if a := runtime.MemStats.Alloc; a != 0 { + runtime.ReadMemStats(&memstats) + if a := memstats.Alloc - stacks; a != 0 { println("allocated ", j, ": wrong stats: during=", during, " after=", a, " (want 0)") panic("fail") } diff --git a/test/mallocrep1.go b/test/mallocrep1.go index 0b1479900e6..f9d7286efd9 100644 --- a/test/mallocrep1.go +++ b/test/mallocrep1.go @@ -20,7 +20,7 @@ var reverse = flag.Bool("r", false, "reverse") var longtest = flag.Bool("l", false, "long test") var b []*byte -var stats = &runtime.MemStats +var stats = new(runtime.MemStats) func OkAmount(size, n uintptr) bool { if n < size { @@ -42,7 +42,7 @@ func AllocAndFree(size, count int) { if *chatty { fmt.Printf("size=%d count=%d ...\n", size, count) } - runtime.UpdateMemStats() + runtime.ReadMemStats(stats) n1 := stats.Alloc for i := 0; i < count; i++ { b[i] = runtime.Alloc(uintptr(size)) @@ -51,13 +51,13 @@ func AllocAndFree(size, count int) { println("lookup failed: got", base, n, "for", b[i]) panic("fail") } - runtime.UpdateMemStats() + runtime.ReadMemStats(stats) if stats.Sys > 1e9 { println("too much memory allocated") panic("fail") } } - runtime.UpdateMemStats() + runtime.ReadMemStats(stats) n2 := stats.Alloc if *chatty { fmt.Printf("size=%d count=%d stats=%+v\n", size, count, *stats) @@ -75,17 +75,17 @@ func AllocAndFree(size, count int) { panic("fail") } runtime.Free(b[i]) - runtime.UpdateMemStats() + runtime.ReadMemStats(stats) if stats.Alloc != uint64(alloc-n) { println("free alloc got", stats.Alloc, "expected", alloc-n, "after free of", n) panic("fail") } - if runtime.MemStats.Sys > 1e9 { + if stats.Sys > 1e9 { println("too much memory allocated") panic("fail") } } - runtime.UpdateMemStats() + runtime.ReadMemStats(stats) n4 := stats.Alloc if *chatty {