1 /**
2 * Contains the garbage collector configuration.
3 *
4 * Copyright: Copyright Digital Mars 2016
5 * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
6 */
7 
8 module core.gc.config;
9 
10 import core.stdc.stdio;
11 import core.internal.parseoptions;
12 
13 __gshared Config config;
14 
15 struct Config
16 {
17     bool disable;            // start disabled
18     bool fork = false;       // optional concurrent behaviour
19     ubyte profile;           // enable profiling with summary when terminating program
20     string gc = "conservative"; // select gc implementation conservative|precise|manual
21 
22     @MemVal size_t initReserve;      // initial reserve (bytes)
23     @MemVal size_t minPoolSize = 1  << 20;  // initial and minimum pool size (bytes)
24     @MemVal size_t maxPoolSize = 64 << 20;  // maximum pool size (bytes)
25     @MemVal size_t incPoolSize = 3  << 20;  // pool size increment (bytes)
26     uint parallel = 99;      // number of additional threads for marking (limited by cpuid.threadsPerCPU-1)
27     float heapSizeFactor = 2.0; // heap size to used memory ratio
28     string cleanup = "collect"; // select gc cleanup method none|collect|finalize
29 
30 @nogc nothrow:
31 
32     bool initialize()
33     {
34         return initConfigOptions(this, "gcopt");
35     }
36 
37     void help() @nogc nothrow
38     {
39         import core.gc.registry : registeredGCFactories;
40 
41         printf("GC options are specified as white space separated assignments:
42     disable:0|1    - start disabled (%d)
43     fork:0|1       - set fork behaviour (%d)
44     profile:0|1|2  - enable profiling with summary when terminating program (%d)
45     gc:".ptr, disable, fork, profile);
46         foreach (i, entry; registeredGCFactories)
47         {
48             if (i) printf("|");
49             printf("%.*s", cast(int) entry.name.length, entry.name.ptr);
50         }
51         auto _initReserve = initReserve.bytes2prettyStruct;
52         auto _minPoolSize = minPoolSize.bytes2prettyStruct;
53         auto _maxPoolSize = maxPoolSize.bytes2prettyStruct;
54         auto _incPoolSize = incPoolSize.bytes2prettyStruct;
55         printf(" - select gc implementation (default = conservative)
56 
57     initReserve:N  - initial memory to reserve in MB (%lld%c)
58     minPoolSize:N  - initial and minimum pool size in MB (%lld%c)
59     maxPoolSize:N  - maximum pool size in MB (%lld%c)
60     incPoolSize:N  - pool size increment MB (%lld%c)
61     parallel:N     - number of additional threads for marking (%lld)
62     heapSizeFactor:N - targeted heap size to used memory ratio (%g)
63     cleanup:none|collect|finalize - how to treat live objects when terminating (collect)
64 
65     Memory-related values can use B, K, M or G suffixes.
66 ".ptr,
67                _initReserve.v, _initReserve.u,
68                _minPoolSize.v, _minPoolSize.u,
69                _maxPoolSize.v, _maxPoolSize.u,
70                _incPoolSize.v, _incPoolSize.u,
71                cast(long)parallel, heapSizeFactor);
72     }
73 
74     string errorName() @nogc nothrow { return "GC"; }
75 }
76 
77 private struct PrettyBytes
78 {
79     long v;
80     char u; /// unit
81 }
82 
83 pure @nogc nothrow:
84 
85 private PrettyBytes bytes2prettyStruct(size_t val)
86 {
87     char c = prettyBytes(val);
88 
89     return PrettyBytes(val, c);
90 }
91 
92 private static char prettyBytes(ref size_t val)
93 {
94     char sym = 'B';
95 
96     if (val == 0)
97         return sym;
98 
99     char[3] units = ['K', 'M', 'G'];
100 
101     foreach (u; units)
102         if (val % (1 << 10) == 0)
103         {
104             val /= (1 << 10);
105             sym = u;
106         }
107         else if (sym != 'B')
108             break;
109 
110     return sym;
111 }
112 unittest
113 {
114     size_t v = 1024;
115     assert(prettyBytes(v) == 'K');
116     assert(v == 1);
117 
118     v = 1025;
119     assert(prettyBytes(v) == 'B');
120     assert(v == 1025);
121 
122     v = 1024UL * 1024 * 1024 * 3;
123     assert(prettyBytes(v) == 'G');
124     assert(v == 3);
125 
126     v = 1024 * 1024 + 1;
127     assert(prettyBytes(v) == 'B');
128     assert(v == 1024 * 1024 + 1);
129 }