1 /**
2 Copyright: Copyright (c) 2020, Joakim Brännström. All rights reserved.
3 License: MPL-2
4 Author: Joakim Brännström (joakim.brannstrom@gmx.com)
5 
6 This Source Code Form is subject to the terms of the Mozilla Public License,
7 v.2.0. If a copy of the MPL was not distributed with this file, You can obtain
8 one at http://mozilla.org/MPL/2.0/.
9 */
10 module dextool.gc;
11 
12 import std.concurrency;
13 import std.datetime : SysTime, Clock, dur;
14 
15 /** Reduces the used memory by the GC and free the heap to the OS.
16  *
17  * To avoid calling this too often the struct have a timer to ensure it is
18  * callled at most ones every minute.
19  *
20  * TODO: maybe add functionality to call it more often when above e.g. 50% memory usage?
21  */
22 struct MemFree {
23     private {
24         bool isRunning;
25         Tid bg;
26     }
27 
28     ~this() @trusted {
29         if (!isRunning)
30             return;
31         scope (exit)
32             isRunning = false;
33         send(bg, Msg.stop);
34     }
35 
36     /** Start a background thread to do the work.
37      *
38      * It terminates when the destructor is called.
39      */
40     void start() @trusted {
41         scope (success)
42             isRunning = true;
43         bg = spawn(&tick);
44     }
45 
46 }
47 
48 private:
49 
50 enum Msg {
51     stop,
52 }
53 
54 void tick() nothrow {
55     import core.thread : Thread;
56     import core.time : dur;
57     import core.memory : GC;
58 
59     const tickInterval = 1.dur!"minutes";
60 
61     bool running = true;
62     SysTime next = Clock.currTime + tickInterval;
63     while (running) {
64         try {
65             receiveTimeout(tickInterval, (Msg x) { running = false; });
66         } catch (Exception e) {
67             running = false;
68         }
69 
70         GC.collect;
71         GC.minimize;
72         malloc_trim(0);
73     }
74 }
75 
76 // malloc_trim - release free memory from the heap
77 extern (C) int malloc_trim(size_t pad) nothrow @system;