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
128
129
|
/**
* Contains the garbage collector configuration.
*
* Copyright: Copyright Digital Mars 2016
* License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
*/
module core.gc.config;
import core.internal.parseoptions;
import core.stdc.stdio : printf;
__gshared Config config;
struct Config
{
bool disable; // start disabled
bool fork = false; // optional concurrent behaviour
ubyte profile; // enable profiling with summary when terminating program
string gc = "conservative"; // select gc implementation conservative|precise|manual
@MemVal size_t initReserve; // initial reserve (bytes)
@MemVal size_t minPoolSize = 1 << 20; // initial and minimum pool size (bytes)
@MemVal size_t maxPoolSize = 64 << 20; // maximum pool size (bytes)
@MemVal size_t incPoolSize = 3 << 20; // pool size increment (bytes)
uint parallel = 99; // number of additional threads for marking (limited by cpuid.threadsPerCPU-1)
float heapSizeFactor = 2.0; // heap size to used memory ratio
string cleanup = "collect"; // select gc cleanup method none|collect|finalize
@nogc nothrow:
bool initialize()
{
return initConfigOptions(this, "gcopt");
}
void help() @nogc nothrow
{
import core.gc.registry : registeredGCFactories;
printf("GC options are specified as white space separated assignments:
disable:0|1 - start disabled (%d)
fork:0|1 - set fork behaviour (%d)
profile:0|1|2 - enable profiling with summary when terminating program (%d)
gc:".ptr, disable, fork, profile);
foreach (i, entry; registeredGCFactories)
{
if (i) printf("|");
printf("%.*s", cast(int) entry.name.length, entry.name.ptr);
}
auto _initReserve = initReserve.bytes2prettyStruct;
auto _minPoolSize = minPoolSize.bytes2prettyStruct;
auto _maxPoolSize = maxPoolSize.bytes2prettyStruct;
auto _incPoolSize = incPoolSize.bytes2prettyStruct;
printf(" - select gc implementation (default = conservative)
initReserve:N - initial memory to reserve in MB (%lld%c)
minPoolSize:N - initial and minimum pool size in MB (%lld%c)
maxPoolSize:N - maximum pool size in MB (%lld%c)
incPoolSize:N - pool size increment MB (%lld%c)
parallel:N - number of additional threads for marking (%lld)
heapSizeFactor:N - targeted heap size to used memory ratio (%g)
cleanup:none|collect|finalize - how to treat live objects when terminating (collect)
Memory-related values can use B, K, M or G suffixes.
".ptr,
_initReserve.v, _initReserve.u,
_minPoolSize.v, _minPoolSize.u,
_maxPoolSize.v, _maxPoolSize.u,
_incPoolSize.v, _incPoolSize.u,
cast(long)parallel, heapSizeFactor);
}
string errorName() @nogc nothrow { return "GC"; }
}
private struct PrettyBytes
{
long v;
char u; /// unit
}
pure @nogc nothrow:
private PrettyBytes bytes2prettyStruct(size_t val)
{
char c = prettyBytes(val);
return PrettyBytes(val, c);
}
private static char prettyBytes(ref size_t val)
{
char sym = 'B';
if (val == 0)
return sym;
char[3] units = ['K', 'M', 'G'];
foreach (u; units)
if (val % (1 << 10) == 0)
{
val /= (1 << 10);
sym = u;
}
else if (sym != 'B')
break;
return sym;
}
unittest
{
size_t v = 1024;
assert(prettyBytes(v) == 'K');
assert(v == 1);
v = 1025;
assert(prettyBytes(v) == 'B');
assert(v == 1025);
v = 1024UL * 1024 * 1024 * 3;
assert(prettyBytes(v) == 'G');
assert(v == 3);
v = 1024 * 1024 + 1;
assert(prettyBytes(v) == 'B');
assert(v == 1024 * 1024 + 1);
}
|