2 * This module contains the options managemente code of the garbage collector.
4 * Copyright: Copyright (C) 2010 Leandro Lucarella <http://www.llucax.com.ar/>
7 * License: Boost Software License - Version 1.0 - August 17th, 2003
9 * Permission is hereby granted, free of charge, to any person or organization
10 * obtaining a copy of the software and accompanying documentation covered by
11 * this license (the "Software") to use, reproduce, display, distribute,
12 * execute, and transmit the Software, and to prepare derivative works of the
13 * Software, and to permit third-parties to whom the Software is furnished to
14 * do so, all subject to the following:
16 * The copyright notices in the Software and this entire statement, including
17 * the above license grant, this restriction and the following disclaimer,
18 * must be included in all copies of the Software, in whole or in part, and
19 * all derivative works of the Software, unless such copies or derivative
20 * works are solely in the form of machine-executable object code generated by
21 * a source language processor.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
26 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
27 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
28 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 * DEALINGS IN THE SOFTWARE.
31 * Authors: Leandro Lucarella
34 module rt.gc.cdgc.opts;
38 import cstdlib = tango.stdc.stdlib;
39 import cstring = tango.stdc.string;
40 import cerrno = tango.stdc.errno;
41 debug (PRINTF) import tango.stdc.stdio: printf;
47 const MAX_OPT_LEN = 256;
53 char[MAX_OPT_LEN] log_file = "";
54 char[MAX_OPT_LEN] malloc_stats_file = "";
55 char[MAX_OPT_LEN] collect_stats_file = "";
56 bool sentinel = false;
57 bool mem_stomp = false;
58 version (D_HavePointerMap)
59 bool conservative = false;
61 bool conservative = true;
63 bool eager_alloc = true;
64 bool early_collect = false;
65 uint min_free = 5; // percent of the heap (0-100)
66 size_t prealloc_psize = 0;
67 size_t prealloc_npools = 0;
70 package Options options;
76 int b(bool v) { return v; }
78 printf("rt.gc.cdgc.opts: verbose=%u, log_file='%s', "
79 "malloc_stats_file='%s', collect_stats_file='%s', sentinel=%d, "
80 "mem_stomp=%d, conservative=%d, fork=%d, eager_alloc=%d, "
81 "early_collect=%d, min_free=%u, prealloc_psize=%lu, "
82 "prealloc_npools=%lu\n", verbose, log_file.ptr,
83 malloc_stats_file.ptr, collect_stats_file.ptr, b(sentinel),
84 b(mem_stomp), b(conservative), b(fork), b(eager_alloc),
85 b(early_collect), min_free, prealloc_psize, prealloc_npools);
89 bool cstr_eq(char* s1, char* s2)
91 return cstring.strcmp(s1, s2) == 0;
95 bool parse_bool(char* value)
99 return (cstdlib.atoi(value) != 0);
103 void parse_prealloc(char* value)
107 long size = cstdlib.strtol(value, &end, 10);
108 if (end == value || cerrno.errno) // error parsing
110 size *= 1024 * 1024; // size is supposed to be in MiB
112 if (*end == 'x') { // number of pools specified
113 char* start = end + 1;
114 npools = cstdlib.strtol(start, &end, 10);
115 if (*end != '\0' || end == start || cerrno.errno) // error parsing
118 else if (*end != '\0') { // don't accept trailing garbage
121 if (size > 0 && npools > 0) {
122 options.prealloc_psize = size;
123 options.prealloc_npools = npools;
128 void parse_min_free(char* value)
131 long free = cstdlib.strtol(value, &end, 10);
132 if (*end != '\0' || end == value || cerrno.errno || free < 0 || free > 100)
134 options.min_free = free;
138 void process_option(char* opt_name, char* opt_value)
140 if (cstr_eq(opt_name, "verbose"))
141 options.verbose = cstdlib.atoi(opt_value);
142 else if (cstr_eq(opt_name, "log_file"))
143 cstring.strcpy(options.log_file.ptr, opt_value);
144 else if (cstr_eq(opt_name, "malloc_stats_file"))
145 cstring.strcpy(options.malloc_stats_file.ptr, opt_value);
146 else if (cstr_eq(opt_name, "collect_stats_file"))
147 cstring.strcpy(options.collect_stats_file.ptr, opt_value);
148 else if (cstr_eq(opt_name, "sentinel"))
149 options.sentinel = parse_bool(opt_value);
150 else if (cstr_eq(opt_name, "mem_stomp"))
151 options.mem_stomp = parse_bool(opt_value);
152 else if (cstr_eq(opt_name, "conservative"))
153 options.conservative = parse_bool(opt_value);
154 else if (cstr_eq(opt_name, "fork"))
155 options.fork = parse_bool(opt_value);
156 else if (cstr_eq(opt_name, "eager_alloc"))
157 options.eager_alloc = parse_bool(opt_value);
158 else if (cstr_eq(opt_name, "early_collect"))
159 options.early_collect = parse_bool(opt_value);
160 else if (cstr_eq(opt_name, "min_free"))
161 parse_min_free(opt_value);
162 else if (cstr_eq(opt_name, "pre_alloc"))
163 parse_prealloc(opt_value);
167 package void parse(char* opts_string)
169 char[MAX_OPT_LEN] opt_name;
171 char[MAX_OPT_LEN] opt_value;
173 char* curr = opt_name.ptr;
175 if (opts_string is null) {
176 debug (PRINTF) printf("rt.gc.cdgc.opts: no options overriden\n");
179 for (; *opts_string != '\0'; opts_string++)
181 char c = *opts_string;
182 if (i == MAX_OPT_LEN)
189 switch (*opts_string)
193 process_option(opt_name.ptr, opt_value.ptr);
201 curr = opt_value.ptr;
209 if (i == MAX_OPT_LEN)
212 process_option(opt_name.ptr, opt_value.ptr);
213 debug (PRINTF) print_options();
220 assert (verbose == 0);
221 assert (log_file[0] == '\0');
222 assert (sentinel == false);
223 assert (mem_stomp == false);
224 assert (conservative == false);
225 assert (fork == true);
226 assert (eager_alloc == true);
227 assert (early_collect == false);
228 assert (prealloc_psize == 0);
229 assert (prealloc_npools == 0);
230 assert (min_free == 5);
234 assert (verbose == 0);
235 assert (log_file[0] == '\0');
236 assert (sentinel == false);
237 assert (mem_stomp == true);
238 assert (conservative == false);
239 assert (fork == true);
240 assert (eager_alloc == true);
241 assert (early_collect == false);
242 assert (prealloc_psize == 0);
243 assert (prealloc_npools == 0);
244 assert (min_free == 5);
246 parse("mem_stomp=0:verbose=2:conservative:fork=0:eager_alloc=0");
248 assert (verbose == 2);
249 assert (log_file[0] == '\0');
250 assert (sentinel == false);
251 assert (mem_stomp == false);
252 assert (conservative == true);
253 assert (fork == false);
254 assert (eager_alloc == false);
255 assert (early_collect == false);
256 assert (prealloc_psize == 0);
257 assert (prealloc_npools == 0);
258 assert (min_free == 5);
260 parse("log_file=12345 67890:verbose=1:sentinel=4:mem_stomp=1");
262 assert (verbose == 1);
263 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
264 assert (sentinel == true);
265 assert (mem_stomp == true);
266 assert (conservative == true);
267 assert (fork == false);
268 assert (eager_alloc == false);
269 assert (early_collect == false);
270 assert (prealloc_psize == 0);
271 assert (prealloc_npools == 0);
272 assert (min_free == 5);
274 parse("pre_alloc:min_free=30:early_collect");
276 assert (verbose == 1);
277 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
278 assert (sentinel == true);
279 assert (mem_stomp == true);
280 assert (conservative == true);
281 assert (fork == false);
282 assert (eager_alloc == false);
283 assert (early_collect == true);
284 assert (prealloc_psize == 0);
285 assert (prealloc_npools == 0);
286 assert (min_free == 30);
288 parse("pre_alloc=1:early_collect=0");
290 assert (verbose == 1);
291 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
292 assert (sentinel == true);
293 assert (mem_stomp == true);
294 assert (conservative == true);
295 assert (fork == false);
296 assert (eager_alloc == false);
297 assert (early_collect == false);
298 assert (prealloc_psize == 1 * 1024 * 1024);
299 assert (prealloc_npools == 1);
300 assert (min_free == 30);
302 parse("pre_alloc=5a:min_free=101");
304 assert (verbose == 1);
305 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
306 assert (sentinel == true);
307 assert (mem_stomp == true);
308 assert (conservative == true);
309 assert (fork == false);
310 assert (eager_alloc == false);
311 assert (early_collect == false);
312 assert (prealloc_psize == 1 * 1024 * 1024);
313 assert (prealloc_npools == 1);
314 assert (min_free == 30);
316 parse("pre_alloc=5x:min_free=-1");
318 assert (verbose == 1);
319 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
320 assert (sentinel == true);
321 assert (mem_stomp == true);
322 assert (conservative == true);
323 assert (fork == false);
324 assert (eager_alloc == false);
325 assert (early_collect == false);
326 assert (prealloc_psize == 1 * 1024 * 1024);
327 assert (prealloc_npools == 1);
328 assert (min_free == 30);
330 parse("pre_alloc=09x010:min_free=10a");
332 assert (verbose == 1);
333 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
334 assert (sentinel == true);
335 assert (mem_stomp == true);
336 assert (conservative == true);
337 assert (fork == false);
338 assert (eager_alloc == false);
339 assert (early_collect == false);
340 assert (prealloc_psize == 9 * 1024 * 1024);
341 assert (prealloc_npools == 10);
342 assert (min_free == 30);
344 parse("pre_alloc=5x2:min_free=1.0");
346 assert (verbose == 1);
347 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
348 assert (sentinel == true);
349 assert (mem_stomp == true);
350 assert (conservative == true);
351 assert (fork == false);
352 assert (eager_alloc == false);
353 assert (early_collect == false);
354 assert (prealloc_psize == 5 * 1024 * 1024);
355 assert (prealloc_npools == 2);
356 assert (min_free == 30);
358 parse("pre_alloc=9x5x:min_free=-1");
360 assert (verbose == 1);
361 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
362 assert (sentinel == true);
363 assert (mem_stomp == true);
364 assert (conservative == true);
365 assert (fork == false);
366 assert (eager_alloc == false);
367 assert (early_collect == false);
368 assert (prealloc_psize == 5 * 1024 * 1024);
369 assert (prealloc_npools == 2);
370 assert (min_free == 30);
372 parse("pre_alloc=9x-5:min_free=0");
374 assert (verbose == 1);
375 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
376 assert (sentinel == true);
377 assert (mem_stomp == true);
378 assert (conservative == true);
379 assert (fork == false);
380 assert (eager_alloc == false);
381 assert (early_collect == false);
382 assert (prealloc_psize == 5 * 1024 * 1024);
383 assert (prealloc_npools == 2);
384 assert (min_free == 0);
386 parse("pre_alloc=0x3x0x4:min_free=100");
388 assert (verbose == 1);
389 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
390 assert (sentinel == true);
391 assert (mem_stomp == true);
392 assert (conservative == true);
393 assert (fork == false);
394 assert (eager_alloc == false);
395 assert (early_collect == false);
396 assert (prealloc_psize == 5 * 1024 * 1024);
397 assert (prealloc_npools == 2);
398 assert (min_free == 100);
402 assert (verbose == 1);
403 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
404 assert (sentinel == true);
405 assert (mem_stomp == true);
406 assert (conservative == true);
407 assert (fork == false);
408 assert (eager_alloc == false);
409 assert (early_collect == false);
410 assert (prealloc_psize == 5 * 1024 * 1024);
411 assert (prealloc_npools == 2);
412 assert (min_free == 100);
416 assert (verbose == 1);
417 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
418 assert (sentinel == true);
419 assert (mem_stomp == true);
420 assert (conservative == true);
421 assert (fork == false);
422 assert (eager_alloc == false);
423 assert (early_collect == false);
424 assert (prealloc_psize == 5 * 1024 * 1024);
425 assert (prealloc_npools == 2);
426 assert (min_free == 100);
430 assert (verbose == 1);
431 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
432 assert (sentinel == true);
433 assert (mem_stomp == true);
434 assert (conservative == true);
435 assert (fork == false);
436 assert (eager_alloc == false);
437 assert (early_collect == false);
438 assert (prealloc_psize == 5 * 1024 * 1024);
439 assert (prealloc_npools == 2);
440 assert (min_free == 100);
444 assert (verbose == 1);
445 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
446 assert (sentinel == true);
447 assert (mem_stomp == true);
448 assert (conservative == true);
449 assert (fork == false);
450 assert (eager_alloc == false);
451 assert (early_collect == false);
452 assert (prealloc_psize == 5 * 1024 * 1024);
453 assert (prealloc_npools == 2);
454 assert (min_free == 100);
459 // vim: set et sw=4 sts=4 :