1 |
/* |
2 |
* balloc.C: Test and time the block allocator |
3 |
* Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team |
4 |
* Rights to this code are documented in doc/poddoc/gplicense.pod |
5 |
* |
6 |
* $Id$ |
7 |
*/ |
8 |
|
9 |
#include "unit/test.h" |
10 |
|
11 |
#ifndef TIMING |
12 |
#define TIMING 0 |
13 |
#endif |
14 |
#ifndef SHOWSIZE |
15 |
#define SHOWSIZE 0 |
16 |
#endif |
17 |
|
18 |
/** |
19 |
* Enabling TIMING will benchmark the block allocator against system malloc (). |
20 |
* Enabling SHOWSIZE will show you the compiler's idea of each structure's size. |
21 |
*/ |
22 |
|
23 |
struct myuser_balloc : object, balloc<myuser_balloc>, has_metadata |
24 |
{ |
25 |
typedef indexing_vector<user_t, &user_t::mu_index> login_vector; |
26 |
typedef indexing_vector<mymemo_t, &mymemo_t::mu_index> memo_vector; |
27 |
typedef unordered_vector<char *> mzignore_vector; // memo ignores |
28 |
|
29 |
myuser_balloc () |
30 |
: has_metadata (MYUSER) |
31 |
{ |
32 |
} |
33 |
|
34 |
char name[NICKLEN]; |
35 |
char pass[NICKLEN]; |
36 |
char email[EMAILLEN]; |
37 |
|
38 |
login_vector logins; /* user_t's currently logged in to this */ |
39 |
time_t registered; |
40 |
time_t lastlogin; |
41 |
|
42 |
list_t chanacs; |
43 |
soper_t *soper; |
44 |
|
45 |
unsigned int flags; |
46 |
|
47 |
memo_vector memos; /* store memos */ |
48 |
unsigned int memoct_new; |
49 |
unsigned int memo_ratelimit_num; /* memos sent recently */ |
50 |
time_t memo_ratelimit_time; /* last time a memo was sent */ |
51 |
mzignore_vector memo_ignores; |
52 |
|
53 |
/* openservices patch */ |
54 |
list_t access_list; |
55 |
|
56 |
list_t nicks; /* registered nicks, must include mu->name if nonempty */ |
57 |
|
58 |
list_t subscriptions; /* presence subscriptors */ |
59 |
|
60 |
protected: |
61 |
void _destroy () |
62 |
{ |
63 |
delete this; |
64 |
} |
65 |
}; |
66 |
|
67 |
struct myuser_noballoc : object, has_metadata |
68 |
{ |
69 |
typedef indexing_vector<user_t, &user_t::mu_index> login_vector; |
70 |
typedef indexing_vector<mymemo_t, &mymemo_t::mu_index> memo_vector; |
71 |
typedef unordered_vector<char *> mzignore_vector; // memo ignores |
72 |
|
73 |
myuser_noballoc () |
74 |
: has_metadata (MYUSER) |
75 |
{ |
76 |
} |
77 |
|
78 |
char name[NICKLEN]; |
79 |
char pass[NICKLEN]; |
80 |
char email[EMAILLEN]; |
81 |
|
82 |
login_vector logins; /* user_t's currently logged in to this */ |
83 |
time_t registered; |
84 |
time_t lastlogin; |
85 |
|
86 |
list_t chanacs; |
87 |
soper_t *soper; |
88 |
|
89 |
unsigned int flags; |
90 |
|
91 |
memo_vector memos; /* store memos */ |
92 |
unsigned int memoct_new; |
93 |
unsigned int memo_ratelimit_num; /* memos sent recently */ |
94 |
time_t memo_ratelimit_time; /* last time a memo was sent */ |
95 |
mzignore_vector memo_ignores; |
96 |
|
97 |
/* openservices patch */ |
98 |
list_t access_list; |
99 |
|
100 |
list_t nicks; /* registered nicks, must include mu->name if nonempty */ |
101 |
|
102 |
list_t subscriptions; /* presence subscriptors */ |
103 |
|
104 |
protected: |
105 |
void _destroy () |
106 |
{ |
107 |
delete this; |
108 |
} |
109 |
}; |
110 |
|
111 |
struct hugestruct : balloc<hugestruct> |
112 |
{ |
113 |
char buf[20000]; |
114 |
char otherbuf[20000]; |
115 |
char hugebuf[20000]; |
116 |
}; |
117 |
|
118 |
struct hugestruct_noballoc |
119 |
{ |
120 |
char buf[20000]; |
121 |
char otherbuf[20000]; |
122 |
char hugebuf[20000]; |
123 |
}; |
124 |
|
125 |
struct tinystruct : balloc<tinystruct> |
126 |
{ |
127 |
char onebyte; |
128 |
}; |
129 |
|
130 |
struct tinystruct_noballoc |
131 |
{ |
132 |
char onebyte; |
133 |
}; |
134 |
|
135 |
// not inline because otherwise the compiler might optimise the loop away |
136 |
static hugestruct * |
137 |
create () |
138 |
{ |
139 |
return new hugestruct; |
140 |
} |
141 |
|
142 |
#if TIMING |
143 |
static hugestruct_noballoc * |
144 |
create_noballoc () |
145 |
{ |
146 |
return new hugestruct_noballoc; |
147 |
} |
148 |
|
149 |
static tinystruct * |
150 |
create_tinystruct () |
151 |
{ |
152 |
return new tinystruct; |
153 |
} |
154 |
|
155 |
static tinystruct_noballoc * |
156 |
create_tinystruct_noballoc () |
157 |
{ |
158 |
return new tinystruct_noballoc; |
159 |
} |
160 |
|
161 |
static myuser_balloc * |
162 |
create_myuser_balloc () |
163 |
{ |
164 |
return new myuser_balloc; |
165 |
} |
166 |
|
167 |
static myuser_noballoc * |
168 |
create_myuser_noballoc () |
169 |
{ |
170 |
return new myuser_noballoc; |
171 |
} |
172 |
#endif |
173 |
|
174 |
test<1> () |
175 |
{ |
176 |
hugestruct *v[3000]; |
177 |
#if TIMING |
178 |
hugestruct_noballoc *n[3000]; |
179 |
tinystruct *t[3000]; |
180 |
tinystruct_noballoc *tn[3000]; |
181 |
myuser_balloc *mub[3000]; |
182 |
myuser_noballoc *munb[3000]; |
183 |
int i = 1000; |
184 |
#if SHOWSIZE |
185 |
std::cout << "sizeof (hugestruct) == " << sizeof (hugestruct) << " (~60KB)\n"; |
186 |
std::cout << "sizeof (hugestruct_noballoc) == " << sizeof (hugestruct_noballoc) << " (~60KB)\n"; |
187 |
std::cout << "sizeof (tinystruct) == " << sizeof (tinystruct) << " (~16B)\n"; |
188 |
std::cout << "sizeof (tinystruct_noballoc) == " << sizeof (tinystruct_noballoc) << " (~1B)\n"; |
189 |
std::cout << "sizeof (myuser_balloc) == " << sizeof (myuser_balloc) << " (~500B)\n"; |
190 |
std::cout << "sizeof (myuser_noballoc) == " << sizeof (myuser_noballoc) << " (~500B)\n"; |
191 |
#endif |
192 |
|
193 |
double start = now (); |
194 |
while (--i) |
195 |
{ |
196 |
#endif |
197 |
for (int j = 0; j < 3000; j++) |
198 |
v[j] = create (); |
199 |
for (int j = 0; j < 3000; j++) |
200 |
delete v[j]; |
201 |
#if TIMING |
202 |
} |
203 |
double end = now (); |
204 |
std::cout << end - start << " seconds (huge struct balloc)\n"; |
205 |
|
206 |
i = 1000; |
207 |
start = now (); |
208 |
while (--i) |
209 |
{ |
210 |
for (int j = 0; j < 3000; j++) |
211 |
n[j] = create_noballoc (); |
212 |
for (int j = 0; j < 3000; j++) |
213 |
delete n[j]; |
214 |
} |
215 |
end = now (); |
216 |
std::cout << end - start << " seconds (huge struct system malloc)\n"; |
217 |
|
218 |
i = 1000; |
219 |
start = now (); |
220 |
while (--i) |
221 |
{ |
222 |
for (int j = 0; j < 3000; j++) |
223 |
t[j] = create_tinystruct (); |
224 |
for (int j = 0; j < 3000; j++) |
225 |
delete t[j]; |
226 |
} |
227 |
end = now (); |
228 |
std::cout << end - start << " seconds (tiny struct balloc)\n"; |
229 |
|
230 |
i = 1000; |
231 |
start = now (); |
232 |
while (--i) |
233 |
{ |
234 |
for (int j = 0; j < 3000; j++) |
235 |
tn[j] = create_tinystruct_noballoc (); |
236 |
for (int j = 0; j < 3000; j++) |
237 |
delete tn[j]; |
238 |
} |
239 |
end = now (); |
240 |
std::cout << end - start << " seconds (tiny struct system malloc)\n"; |
241 |
|
242 |
i = 1000; |
243 |
start = now (); |
244 |
while (--i) |
245 |
{ |
246 |
for (int j = 0; j < 3000; j++) |
247 |
mub[j] = create_myuser_balloc (); |
248 |
for (int j = 0; j < 3000; j++) |
249 |
delete mub[j]; |
250 |
} |
251 |
end = now (); |
252 |
std::cout << end - start << " seconds (myuser balloc)\n"; |
253 |
|
254 |
i = 1000; |
255 |
start = now (); |
256 |
while (--i) |
257 |
{ |
258 |
for (int j = 0; j < 3000; j++) |
259 |
munb[j] = create_myuser_noballoc (); |
260 |
for (int j = 0; j < 3000; j++) |
261 |
delete munb[j]; |
262 |
} |
263 |
end = now (); |
264 |
std::cout << end - start << " seconds (myuser system malloc)\n"; |
265 |
#endif |
266 |
|
267 |
hugestruct::finalise (); |
268 |
tinystruct::finalise (); |
269 |
myuser_balloc::finalise (); |
270 |
} |
271 |
|
272 |
#include "unit/runtest.h" |