| /** | |
| * 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; | |
| private __gshared bool _initialized; | |
| 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() | |
| { | |
| if (!_initialized) | |
| _initialized = initConfigOptions(this, "gcopt"); | |
| return _initialized; | |
| } | |
| 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); | |
| } |