]> git.llucax.com Git - software/dgc/cdgc.git/blob - rt/gc/cdgc/opts.d
Try to keep the memory usage low more aggressively
[software/dgc/cdgc.git] / rt / gc / cdgc / opts.d
1 /**
2  * This module contains the options managemente code of the garbage collector.
3  *
4  * Copyright: Copyright (C) 2010 Leandro Lucarella <http://www.llucax.com.ar/>
5  *            All rights reserved.
6  *
7  * License: Boost Software License - Version 1.0 - August 17th, 2003
8  *
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:
15  *
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.
22  *
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.
30  *
31  * Authors: Leandro Lucarella
32  */
33
34 module rt.gc.cdgc.opts;
35
36 import cstdlib = tango.stdc.stdlib;
37 import cstring = tango.stdc.string;
38 import cerrno = tango.stdc.errno;
39
40
41 private:
42
43
44 const MAX_OPT_LEN = 256;
45
46
47 struct Options
48 {
49     uint verbose = 0;
50     char[MAX_OPT_LEN] log_file = "";
51     char[MAX_OPT_LEN] malloc_stats_file = "";
52     char[MAX_OPT_LEN] collect_stats_file = "";
53     bool sentinel = false;
54     bool mem_stomp = false;
55     bool conservative = false;
56     bool fork = true;
57     bool eager_alloc = true;
58     size_t prealloc_psize = 0;
59     size_t prealloc_npools = 0;
60 }
61
62 package Options options;
63
64
65 bool cstr_eq(char* s1, char* s2)
66 {
67     return cstring.strcmp(s1, s2) == 0;
68 }
69
70
71 bool parse_bool(char* value)
72 {
73     if (value[0] == '\0')
74         return true;
75     return (cstdlib.atoi(value) != 0);
76 }
77
78
79 void parse_prealloc(char* value)
80 {
81     char* end;
82     cerrno.errno = 0;
83     long size = cstdlib.strtol(value, &end, 10);
84     if (end == value || cerrno.errno) // error parsing
85         return;
86     size *= 1024 * 1024; // size is supposed to be in MiB
87     long npools = 1;
88     if (*end == 'x') { // number of pools specified
89         char* start = end + 1;
90         npools = cstdlib.strtol(start, &end, 10);
91         if (*end != '\0' || end == start || cerrno.errno) // error parsing
92             return;
93     }
94     else if (*end != '\0') { // don't accept trailing garbage
95         return;
96     }
97     if (size > 0 && npools > 0) {
98         options.prealloc_psize = size;
99         options.prealloc_npools = npools;
100     }
101 }
102
103
104 void process_option(char* opt_name, char* opt_value)
105 {
106     if (cstr_eq(opt_name, "verbose"))
107         options.verbose = cstdlib.atoi(opt_value);
108     else if (cstr_eq(opt_name, "log_file"))
109         cstring.strcpy(options.log_file.ptr, opt_value);
110     else if (cstr_eq(opt_name, "malloc_stats_file"))
111         cstring.strcpy(options.malloc_stats_file.ptr, opt_value);
112     else if (cstr_eq(opt_name, "collect_stats_file"))
113         cstring.strcpy(options.collect_stats_file.ptr, opt_value);
114     else if (cstr_eq(opt_name, "sentinel"))
115         options.sentinel = parse_bool(opt_value);
116     else if (cstr_eq(opt_name, "mem_stomp"))
117         options.mem_stomp = parse_bool(opt_value);
118     else if (cstr_eq(opt_name, "conservative"))
119         options.conservative = parse_bool(opt_value);
120     else if (cstr_eq(opt_name, "fork"))
121         options.fork = parse_bool(opt_value);
122     else if (cstr_eq(opt_name, "eager_alloc"))
123         options.eager_alloc = parse_bool(opt_value);
124     else if (cstr_eq(opt_name, "pre_alloc"))
125         parse_prealloc(opt_value);
126 }
127
128
129 package void parse(char* opts_string)
130 {
131     char[MAX_OPT_LEN] opt_name;
132     opt_name[0] = '\0';
133     char[MAX_OPT_LEN] opt_value;
134     opt_value[0] = '\0';
135     char* curr = opt_name.ptr;
136     size_t i = 0;
137     if (opts_string is null)
138         return;
139     for (; *opts_string != '\0'; opts_string++)
140     {
141         char c = *opts_string;
142         if (i == MAX_OPT_LEN)
143         {
144             if (c != ':')
145                 continue;
146             else
147                 i--;
148         }
149         switch (*opts_string)
150         {
151         case ':':
152             curr[i] = '\0';
153             process_option(opt_name.ptr, opt_value.ptr);
154             i = 0;
155             opt_name[0] = '\0';
156             opt_value[0] = '\0';
157             curr = opt_name.ptr;
158             break;
159         case '=':
160             opt_name[i] = '\0';
161             curr = opt_value.ptr;
162             i = 0;
163             break;
164         default:
165             curr[i] = c;
166             ++i;
167         }
168     }
169     if (i == MAX_OPT_LEN)
170         i--;
171     curr[i] = '\0';
172     process_option(opt_name.ptr, opt_value.ptr);
173 }
174
175
176 unittest
177 {
178     with (options) {
179         assert (verbose == 0);
180         assert (log_file[0] == '\0');
181         assert (sentinel == false);
182         assert (mem_stomp == false);
183         assert (conservative == false);
184         assert (fork == true);
185         assert (eager_alloc == true);
186         assert (prealloc_psize == 0);
187         assert (prealloc_npools == 0);
188     }
189     parse("mem_stomp");
190     with (options) {
191         assert (verbose == 0);
192         assert (log_file[0] == '\0');
193         assert (sentinel == false);
194         assert (mem_stomp == true);
195         assert (conservative == false);
196         assert (fork == true);
197         assert (eager_alloc == true);
198         assert (prealloc_psize == 0);
199         assert (prealloc_npools == 0);
200     }
201     parse("mem_stomp=0:verbose=2:conservative:fork=0:eager_alloc=0");
202     with (options) {
203         assert (verbose == 2);
204         assert (log_file[0] == '\0');
205         assert (sentinel == false);
206         assert (mem_stomp == false);
207         assert (conservative == true);
208         assert (fork == false);
209         assert (eager_alloc == false);
210         assert (prealloc_psize == 0);
211         assert (prealloc_npools == 0);
212     }
213     parse("log_file=12345 67890:verbose=1:sentinel=4:mem_stomp=1");
214     with (options) {
215         assert (verbose == 1);
216         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
217         assert (sentinel == true);
218         assert (mem_stomp == true);
219         assert (conservative == true);
220         assert (fork == false);
221         assert (eager_alloc == false);
222         assert (prealloc_psize == 0);
223         assert (prealloc_npools == 0);
224     }
225     parse("pre_alloc");
226     with (options) {
227         assert (verbose == 1);
228         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
229         assert (sentinel == true);
230         assert (mem_stomp == true);
231         assert (conservative == true);
232         assert (fork == false);
233         assert (eager_alloc == false);
234         assert (prealloc_psize == 0);
235         assert (prealloc_npools == 0);
236     }
237     parse("pre_alloc=1");
238     with (options) {
239         assert (verbose == 1);
240         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
241         assert (sentinel == true);
242         assert (mem_stomp == true);
243         assert (conservative == true);
244         assert (fork == false);
245         assert (eager_alloc == false);
246         assert (prealloc_psize == 1 * 1024 * 1024);
247         assert (prealloc_npools == 1);
248     }
249     parse("pre_alloc=5a");
250     with (options) {
251         assert (verbose == 1);
252         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
253         assert (sentinel == true);
254         assert (mem_stomp == true);
255         assert (conservative == true);
256         assert (fork == false);
257         assert (eager_alloc == false);
258         assert (prealloc_psize == 1 * 1024 * 1024);
259         assert (prealloc_npools == 1);
260     }
261     parse("pre_alloc=5x");
262     with (options) {
263         assert (verbose == 1);
264         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
265         assert (sentinel == true);
266         assert (mem_stomp == true);
267         assert (conservative == true);
268         assert (fork == false);
269         assert (eager_alloc == false);
270         assert (prealloc_psize == 1 * 1024 * 1024);
271         assert (prealloc_npools == 1);
272     }
273     parse("pre_alloc=09x010");
274     with (options) {
275         assert (verbose == 1);
276         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
277         assert (sentinel == true);
278         assert (mem_stomp == true);
279         assert (conservative == true);
280         assert (fork == false);
281         assert (eager_alloc == false);
282         assert (prealloc_psize == 9 * 1024 * 1024);
283         assert (prealloc_npools == 10);
284     }
285     parse("pre_alloc=5x2");
286     with (options) {
287         assert (verbose == 1);
288         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
289         assert (sentinel == true);
290         assert (mem_stomp == true);
291         assert (conservative == true);
292         assert (fork == false);
293         assert (eager_alloc == false);
294         assert (prealloc_psize == 5 * 1024 * 1024);
295         assert (prealloc_npools == 2);
296     }
297     parse("pre_alloc=9x5x");
298     with (options) {
299         assert (verbose == 1);
300         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
301         assert (sentinel == true);
302         assert (mem_stomp == true);
303         assert (conservative == true);
304         assert (fork == false);
305         assert (eager_alloc == false);
306         assert (prealloc_psize == 5 * 1024 * 1024);
307         assert (prealloc_npools == 2);
308     }
309     parse("pre_alloc=9x-5");
310     with (options) {
311         assert (verbose == 1);
312         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
313         assert (sentinel == true);
314         assert (mem_stomp == true);
315         assert (conservative == true);
316         assert (fork == false);
317         assert (eager_alloc == false);
318         assert (prealloc_psize == 5 * 1024 * 1024);
319         assert (prealloc_npools == 2);
320     }
321     parse("pre_alloc=0x3x0x4");
322     with (options) {
323         assert (verbose == 1);
324         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
325         assert (sentinel == true);
326         assert (mem_stomp == true);
327         assert (conservative == true);
328         assert (fork == false);
329         assert (eager_alloc == false);
330         assert (prealloc_psize == 5 * 1024 * 1024);
331         assert (prealloc_npools == 2);
332     }
333     parse(null);
334     with (options) {
335         assert (verbose == 1);
336         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
337         assert (sentinel == true);
338         assert (mem_stomp == true);
339         assert (conservative == true);
340         assert (fork == false);
341         assert (eager_alloc == false);
342         assert (prealloc_psize == 5 * 1024 * 1024);
343         assert (prealloc_npools == 2);
344     }
345     parse("");
346     with (options) {
347         assert (verbose == 1);
348         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
349         assert (sentinel == true);
350         assert (mem_stomp == true);
351         assert (conservative == true);
352         assert (fork == false);
353         assert (eager_alloc == false);
354         assert (prealloc_psize == 5 * 1024 * 1024);
355         assert (prealloc_npools == 2);
356     }
357     parse(":");
358     with (options) {
359         assert (verbose == 1);
360         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
361         assert (sentinel == true);
362         assert (mem_stomp == true);
363         assert (conservative == true);
364         assert (fork == false);
365         assert (eager_alloc == false);
366         assert (prealloc_psize == 5 * 1024 * 1024);
367         assert (prealloc_npools == 2);
368     }
369     parse("::::");
370     with (options) {
371         assert (verbose == 1);
372         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
373         assert (sentinel == true);
374         assert (mem_stomp == true);
375         assert (conservative == true);
376         assert (fork == false);
377         assert (eager_alloc == false);
378         assert (prealloc_psize == 5 * 1024 * 1024);
379         assert (prealloc_npools == 2);
380     }
381 }
382
383
384 // vim: set et sw=4 sts=4 :