1
/*
2
 * $Id$
3
 *
4
 * Copyright (C) 2003-2009 JNode.org
5
 *
6
 * This library is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU Lesser General Public License as published
8
 * by the Free Software Foundation; either version 2.1 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful, but 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
14
 * License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with this library; If not, write to the Free Software Foundation, Inc., 
18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
 */
20
21
package org.jnode.vm.memmgr.generational;
22
23
import org.jnode.annotation.Inline;
24
import org.jnode.annotation.MagicPermission;
25
import org.jnode.vm.BootableObject;
26
import org.jnode.vm.memmgr.generational.trigger.ComparatorGCTrigger;
27
import org.jnode.vm.memmgr.generational.trigger.CompoundGCTrigger;
28
import org.jnode.vm.memmgr.generational.trigger.CounterGCTrigger;
29
import org.jnode.vm.memmgr.generational.trigger.FalseGCTrigger;
30
import org.jnode.vm.memmgr.generational.trigger.GCTrigger;
31
import org.jnode.vm.memmgr.generational.trigger.TimerGCTrigger;
32
33
/**
34
 * 
35
 * @author loic rouchon
36
 * 
37
 */
38
@MagicPermission
39
public final class GenGCTriggerManager implements BootableObject {
40
41
    /**
42
     * When this percentage of the free memory has been allocated, a GC is
43
     * triggered (0..1.0)
44
     */
45
    public static float GC_TRIGGER_PERCENTAGE = 0.75f;
46
47
    private final static long youngSpaceTimerTrigger = 2000L;
48
    private final static long tenuredSpaceTimerTrigger = 60000L;
49
    private final static long sweepTimerTrigger = 5000L;
50
    private final static int youngSpaceCounterTrigger = 100000;
51
    private final static int tenuredSpaceCounterTrigger = 250000;
52
    private final static int sweepCounterTrigger = 200000;
53
54
    /**
55
     * The GC thread
56
     */
57
    private GenGCThread gcThread;
58
59
    /**
60
     * The GC free thread
61
     */
62
    private GenGCSweepThread gcSweepThread;
63
64
    /**
65
     * GC young space triggers
66
     */
67
    private final GCTrigger gcYoungSpaceFalseTrigger = new FalseGCTrigger();
68
    private GCTrigger gcYoungSpaceRealTrigger;
69
    private GCTrigger gcYoungSpaceCurrentTrigger;
70
71
    /**
72
     * GC tenured space triggers
73
     */
74
    private final GCTrigger gcTenuredSpaceFalseTrigger = new FalseGCTrigger();
75
    private GCTrigger gcTenuredSpaceRealTrigger;
76
    private GCTrigger gcTenuredSpaceCurrentTrigger;
77
78
    /**
79
     * GCSweep triggers
80
     */
81
    private final GCTrigger gcSweepFalseTrigger = new FalseGCTrigger();
82
    private GCTrigger gcSweepRealTrigger;
83
    private GCTrigger gcSweepCurrentTrigger;
84
85
    /**
86
     * GC Allocated size trigger
87
     */
88
    private final ComparatorGCTrigger allocatedSizeTrigger = new ComparatorGCTrigger(
89
            Integer.MAX_VALUE);
90
91
    private boolean traceTriggers = true;
92
93
    public GenGCTriggerManager() {
94
        disableGCTriggers();
95
    }
96
97
    public void initialize(GenGCThread gcThread, GenGCSweepThread gcSweepThread,
98
            boolean traceTriggers) {
99
        this.gcThread = gcThread;
100
        this.gcSweepThread = gcSweepThread;
101
        this.traceTriggers = traceTriggers;
102
        initializeTriggers();
103
    }
104
105
    private void initializeTriggers() {
106
        intializeGCYoungSpaceTriggers();
107
        intializeGCTenuredSpaceTriggers();
108
        intializeGCSweepTriggers();
109
        disableGCTriggers();
110
    }
111
112
    public void check() {
113
        checkGCTenuredSpaceTriggers();
114
        checkGCYoungSpaceTriggers();
115
        checkGCSweepTriggers();
116
    }
117
118
    public void enableGCTriggers() {
119
        // gcYoungSpaceCurrentTrigger = gcYoungSpaceRealTrigger;
120
        gcTenuredSpaceCurrentTrigger = gcTenuredSpaceRealTrigger;
121
        gcSweepCurrentTrigger = gcSweepRealTrigger;
122
        reset();
123
    }
124
125
    public void disableGCTriggers() {
126
        gcYoungSpaceCurrentTrigger = gcYoungSpaceFalseTrigger;
127
        gcTenuredSpaceCurrentTrigger = gcTenuredSpaceFalseTrigger;
128
        gcSweepCurrentTrigger = gcSweepFalseTrigger;
129
    }
130
131
    public void setFreeMemory(long freeMemory) {
132
        allocatedSizeTrigger.setLimit((int) Math.min(Integer.MAX_VALUE, freeMemory
133
                * GC_TRIGGER_PERCENTAGE));
134
    }
135
136
    public void incrementAllocatedSizeSinceLastGCBy(int value) {
137
        allocatedSizeTrigger.incrementCounterValue(value);
138
    }
139
140
    private void reset() {
141
        gcYoungSpaceCurrentTrigger.reset();
142
        gcTenuredSpaceCurrentTrigger.reset();
143
        gcSweepCurrentTrigger.reset();
144
    }
145
146
    private void intializeGCYoungSpaceTriggers() {
147
        final GCTrigger triggers[] = { new TimerGCTrigger(youngSpaceTimerTrigger),
148
                new CounterGCTrigger(youngSpaceCounterTrigger), allocatedSizeTrigger };
149
        gcYoungSpaceRealTrigger = new CompoundGCTrigger(triggers);
150
    }
151
152
    private void intializeGCTenuredSpaceTriggers() {
153
        final GCTrigger triggers[] = { new TimerGCTrigger(tenuredSpaceTimerTrigger),
154
                new CounterGCTrigger(tenuredSpaceCounterTrigger), allocatedSizeTrigger };
155
        gcTenuredSpaceRealTrigger = new CompoundGCTrigger(triggers);
156
    }
157
158
    private void intializeGCSweepTriggers() {
159
        final GCTrigger triggers[] = { new TimerGCTrigger(sweepTimerTrigger),
160
                new CounterGCTrigger(sweepCounterTrigger) };
161
        gcSweepRealTrigger = new CompoundGCTrigger(triggers);
162
    }
163
164
    @Inline
165
    private void checkGCYoungSpaceTriggers() {
166
        if (gcYoungSpaceCurrentTrigger.check()) {
167
            debug("<alloc:GC trigger/>");
168
            gcThread.triggerMinor(false);
169
        }
170
    }
171
172
    @Inline
173
    private void checkGCTenuredSpaceTriggers() {
174
        if (gcTenuredSpaceCurrentTrigger.check()) {
175
            debug("<alloc:GC young space trigger/>");
176
            gcYoungSpaceCurrentTrigger.reset();
177
            gcThread.triggerMinor(true);
178
            debug("<alloc:GC tenured space trigger/>");
179
            gcThread.triggerMajor(false);
180
        }
181
    }
182
183
    @Inline
184
    private void checkGCSweepTriggers() {
185
        if (gcSweepCurrentTrigger.check()) {
186
            debug("<alloc:GC Sweep trigger/>");
187
            gcSweepThread.trigger(false);
188
        }
189
    }
190
191
    @Inline
192
    private void debug(String txt) {
193
        if (traceTriggers) {
194
            debug(txt);
195
        }
196
    }
197
}