summaryrefslogtreecommitdiff
path: root/test/mallocrep1.go
blob: e78a9ce9ca524875c293e4364943ae1c5e38f0c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// $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, xx1 := 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;
	}
	for j := 1; j <= 1<<22; j<<=1 {
		n := len(b);
		max := uintptr(1<<28);
		if !*longtest {
			max = 1<<22;
		}
		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
			}
		}
	}
}