| // $G $D/$F.go && $L $F.$A && ./$A.out |
| |
| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Repeated malloc test. |
| |
| package main |
| |
| import ( |
| "flag"; |
| "fmt"; |
| "malloc"; |
| "strconv" |
| ) |
| |
| var chatty = flag.Bool("v", false, "chatty"); |
| var reverse = flag.Bool("r", false, "reverse"); |
| var longtest = flag.Bool("l", false, "long test"); |
| |
| var b []*byte; |
| var stats = malloc.GetStats(); |
| |
| func OkAmount(size, n uintptr) bool { |
| if n < size { |
| return false |
| } |
| if size < 16*8 { |
| if n > size+16 { |
| return false |
| } |
| } else { |
| if n > size*9/8 { |
| return false |
| } |
| } |
| return true |
| } |
| |
| func AllocAndFree(size, count int) { |
| if *chatty { |
| fmt.Printf("size=%d count=%d ...\n", size, count); |
| } |
| n1 := stats.Alloc; |
| for i := 0; i < count; i++ { |
| b[i] = malloc.Alloc(uintptr(size)); |
| base, n := malloc.Lookup(b[i]); |
| if base != b[i] || !OkAmount(uintptr(size), n) { |
| panicln("lookup failed: got", base, n, "for", b[i]); |
| } |
| if malloc.GetStats().Sys > 1e9 { |
| panicln("too much memory allocated"); |
| } |
| } |
| n2 := stats.Alloc; |
| if *chatty { |
| fmt.Printf("size=%d count=%d stats=%+v\n", size, count, *stats); |
| } |
| n3 := stats.Alloc; |
| for j := 0; j < count; j++ { |
| i := j; |
| if *reverse { |
| i = count - 1 - j; |
| } |
| alloc := uintptr(stats.Alloc); |
| base, n := malloc.Lookup(b[i]); |
| if base != b[i] || !OkAmount(uintptr(size), n) { |
| panicln("lookup failed: got", base, n, "for", b[i]); |
| } |
| malloc.Free(b[i]); |
| if stats.Alloc != uint64(alloc - n) { |
| panicln("free alloc got", stats.Alloc, "expected", alloc - n, "after free of", n); |
| } |
| if malloc.GetStats().Sys > 1e9 { |
| panicln("too much memory allocated"); |
| } |
| } |
| n4 := stats.Alloc; |
| |
| if *chatty { |
| fmt.Printf("size=%d count=%d stats=%+v\n", size, count, *stats); |
| } |
| if n2-n1 != n3-n4 { |
| panicln("wrong alloc count: ", n2-n1, n3-n4); |
| } |
| } |
| |
| func atoi(s string) int { |
| i, _ := strconv.Atoi(s); |
| return i |
| } |
| |
| func main() { |
| flag.Parse(); |
| b = make([]*byte, 10000); |
| if flag.NArg() > 0 { |
| AllocAndFree(atoi(flag.Arg(0)), atoi(flag.Arg(1))); |
| return; |
| } |
| maxb := 1<<22; |
| if !*longtest { |
| maxb = 1<<19; |
| } |
| for j := 1; j <= maxb; j<<=1 { |
| n := len(b); |
| max := uintptr(1<<28); |
| if !*longtest { |
| max = uintptr(maxb); |
| } |
| if uintptr(j)*uintptr(n) > max { |
| n = int(max / uintptr(j)); |
| } |
| if n < 10 { |
| n = 10; |
| } |
| for m := 1; m <= n; { |
| AllocAndFree(j, m); |
| if m == n { |
| break |
| } |
| m = 5*m/4; |
| if m < 4 { |
| m++ |
| } |
| if m > n { |
| m = n |
| } |
| } |
| } |
| } |