15
15
*/
16
16
package com .orientechnologies .orient .core .memory ;
17
17
18
+ import com .orientechnologies .common .io .OFileUtils ;
19
+ import com .orientechnologies .common .log .OLogManager ;
20
+ import com .orientechnologies .common .profiler .OAbstractProfiler .OProfilerHookValue ;
21
+ import com .orientechnologies .common .profiler .OProfilerMBean .METRIC_TYPE ;
22
+ import com .orientechnologies .orient .core .Orient ;
23
+ import com .orientechnologies .orient .core .config .OGlobalConfiguration ;
24
+
18
25
import java .lang .management .ManagementFactory ;
19
26
import java .lang .management .MemoryMXBean ;
20
27
import java .lang .management .MemoryUsage ;
28
+ import java .lang .ref .Reference ;
21
29
import java .lang .ref .ReferenceQueue ;
22
30
import java .lang .ref .SoftReference ;
23
31
import java .util .ArrayList ;
26
34
import java .util .TimerTask ;
27
35
import java .util .WeakHashMap ;
28
36
29
- import com .orientechnologies .common .io .OFileUtils ;
30
- import com .orientechnologies .common .log .OLogManager ;
31
- import com .orientechnologies .common .profiler .OAbstractProfiler .OProfilerHookValue ;
32
- import com .orientechnologies .common .profiler .OProfilerMBean .METRIC_TYPE ;
33
- import com .orientechnologies .orient .core .Orient ;
34
- import com .orientechnologies .orient .core .config .OGlobalConfiguration ;
35
-
36
37
/**
37
38
* This memory warning system will call the listener when we exceed the percentage of available memory specified. There should only
38
39
* be one instance of this object created, since the usage threshold can only be set to one number.
39
40
*/
40
41
public class OMemoryWatchDog extends Thread {
41
- private final Map <ListenerWrapper , Object > listeners = new WeakHashMap <ListenerWrapper , Object >(128 );
42
- private static long lastGC = 0 ;
43
- private int alertTimes = 0 ;
44
- protected final ReferenceQueue <Object > monitorQueue = new ReferenceQueue <Object >();
45
- protected SoftReference <Object > monitorRef = new SoftReference <Object >(new Object (), monitorQueue );
46
-
42
+ public static final int CHECK_TIMEOUT = 3000 ;
43
+ private static long lastGC = 0 ;
44
+ protected final ReferenceQueue <Object > monitorQueue = new ReferenceQueue <Object >();
45
+ protected SoftReference <Object > monitorRef = new SoftReference <Object >(new Object (), monitorQueue );
47
46
protected final MemoryMXBean memBean ;
48
-
47
+ private final Map <ListenerWrapper , Object > listeners = new WeakHashMap <ListenerWrapper , Object >(128 );
48
+ private int alertTimes = 0 ;
49
49
private long autoFreeCheckEveryMs ;
50
50
private long autoFreeHeapThreshold ;
51
51
52
+ public static interface Listener {
53
+ /**
54
+ * Called when free memory is getting lower.
55
+ *
56
+ * @param iFreeMemory
57
+ * Current used memory
58
+ * @param iFreeMemoryPercentage
59
+ * Max memory
60
+ */
61
+ public void lowMemory (long iFreeMemory , long iFreeMemoryPercentage );
62
+ }
63
+
52
64
/**
53
65
* we want properties of both IdentityHashMap and WeakHashMap
54
66
*/
@@ -84,22 +96,8 @@ public int hashCode() {
84
96
}
85
97
}
86
98
87
- public static interface Listener {
88
- /**
89
- * Called when free memory is getting lower.
90
- *
91
- * @param iFreeMemory
92
- * Current used memory
93
- * @param iFreeMemoryPercentage
94
- * Max memory
95
- */
96
- public void lowMemory (long iFreeMemory , long iFreeMemoryPercentage );
97
- }
98
-
99
99
/**
100
100
* Create the memory watch dog with the default memory threshold.
101
- *
102
- * @param iThreshold
103
101
*/
104
102
public OMemoryWatchDog () {
105
103
super ("OrientDB MemoryWatchDog" );
@@ -113,26 +111,49 @@ public OMemoryWatchDog() {
113
111
start ();
114
112
}
115
113
114
+ public static void freeMemoryForOptimization (final long iDelayTime ) {
115
+ freeMemory (iDelayTime , OGlobalConfiguration .JVM_GC_DELAY_FOR_OPTIMIZE .getValueAsLong ());
116
+ }
117
+
118
+ public static void freeMemoryForResourceCleanup (final long iDelayTime ) {
119
+ freeMemory (iDelayTime , 0 );
120
+ }
121
+
122
+ private static void freeMemory (final long iDelayTime , final long minimalTimeAmount ) {
123
+ final long dateLastGC = System .currentTimeMillis ();
124
+ if (dateLastGC - lastGC > minimalTimeAmount * 1000 ) {
125
+ lastGC = dateLastGC ;
126
+ System .gc ();
127
+
128
+ if (iDelayTime > 0 )
129
+ try {
130
+ Thread .sleep (iDelayTime );
131
+ } catch (InterruptedException e ) {
132
+ Thread .currentThread ().interrupt ();
133
+ }
134
+ }
135
+ }
136
+
116
137
@ Override
117
138
public void run () {
118
139
Orient
119
- .instance ()
120
- .getProfiler ()
121
- .registerHookValue ("system.memory.alerts" , "Number of alerts received by JVM to free memory resources" ,
122
- METRIC_TYPE .COUNTER , new OProfilerHookValue () {
123
- public Object getValue () {
124
- return alertTimes ;
125
- }
126
- });
140
+ .instance ()
141
+ .getProfiler ()
142
+ .registerHookValue ("system.memory.alerts" , "Number of alerts received by JVM to free memory resources" ,
143
+ METRIC_TYPE .COUNTER , new OProfilerHookValue () {
144
+ public Object getValue () {
145
+ return alertTimes ;
146
+ }
147
+ });
127
148
Orient
128
- .instance ()
129
- .getProfiler ()
130
- .registerHookValue ("system.memory.lastGC" , "Date of last System.gc() invocation" , METRIC_TYPE .STAT ,
131
- new OProfilerHookValue () {
132
- public Object getValue () {
133
- return lastGC ;
134
- }
135
- });
149
+ .instance ()
150
+ .getProfiler ()
151
+ .registerHookValue ("system.memory.lastGC" , "Date of last System.gc() invocation" , METRIC_TYPE .STAT ,
152
+ new OProfilerHookValue () {
153
+ public Object getValue () {
154
+ return lastGC ;
155
+ }
156
+ });
136
157
137
158
autoFreeCheckEveryMs = OGlobalConfiguration .MEMORY_AUTOFREE_CHECK_EVERY .getValueAsLong ();
138
159
Orient .instance ().getTimer ().schedule (new TimerTask () {
@@ -167,35 +188,38 @@ public void run() {
167
188
while (true ) {
168
189
try {
169
190
// WAITS FOR THE GC FREE
170
- monitorQueue .remove ();
191
+ final Reference <?> res = monitorQueue .remove (CHECK_TIMEOUT );
171
192
193
+ // CHECK IF HAS BEEN INTERRUPTED
172
194
if (Thread .interrupted ())
195
+ // INTERRUPTED, EXIT FROM THE THREAD'S LOOP!
173
196
break ;
174
197
175
- // GC is freeing memory!
176
- alertTimes ++;
177
- MemoryUsage heapMemory = memBean .getHeapMemoryUsage ();
178
- final long usedHeap = heapMemory .getUsed ();
179
- final long maxHeap = heapMemory .getMax ();
180
- final int usedMemoryPer = (int ) (usedHeap * 100 / maxHeap );
198
+ if ( res != null ) { // GC is freeing memory!
199
+ alertTimes ++;
200
+ MemoryUsage heapMemory = memBean .getHeapMemoryUsage ();
201
+ final long usedHeap = heapMemory .getUsed ();
202
+ final long maxHeap = heapMemory .getMax ();
203
+ final int usedMemoryPer = (int ) (usedHeap * 100 / maxHeap );
181
204
182
- if (OLogManager .instance ().isDebugEnabled ())
183
- OLogManager .instance ().debug (this , "Free memory is low %s of %s (%d%%), calling listeners to free memory..." ,
184
- OFileUtils .getSizeAsString (maxHeap - usedHeap ), OFileUtils .getSizeAsString (maxHeap ), 100 - usedMemoryPer );
205
+ if (OLogManager .instance ().isDebugEnabled ())
206
+ OLogManager .instance ().debug (this , "Free memory is low %s of %s (%d%%), calling listeners to free memory..." ,
207
+ OFileUtils .getSizeAsString (maxHeap - usedHeap ), OFileUtils .getSizeAsString (maxHeap ), 100 - usedMemoryPer );
185
208
186
- final long timer = Orient .instance ().getProfiler ().startChrono ();
209
+ final long timer = Orient .instance ().getProfiler ().startChrono ();
187
210
188
- synchronized (listeners ) {
189
-
E377
for (ListenerWrapper listener : listeners .keySet ()) {
190
- try {
191
- listener .listener .lowMemory (maxHeap - usedHeap , 100 - usedMemoryPer );
192
- } catch (Exception e ) {
193
- e .printStackTrace ();
211
+ synchronized (listeners ) {
212
+ for (ListenerWrapper listener : listeners .keySet ()) {
213
+ try {
214
+ listener .listener .lowMemory (maxHeap - usedHeap , 100 - usedMemoryPer );
215
+ } catch (Exception e ) {
216
+ e .printStackTrace ();
217
+ }
194
218
}
195
219
}
196
- }
197
220
198
- Orient .instance ().getProfiler ().stopChrono ("OMemoryWatchDog.freeResources" , "WatchDog free resources" , timer );
221
+ Orient .instance ().getProfiler ().stopChrono ("OMemoryWatchDog.freeResources" , "WatchDog free resources" , timer );
222
+ }
199
223
200
224
} catch (InterruptedException e ) {
201
225
break ;
@@ -249,14 +273,6 @@ public List<Listener> getListeners() {
249
273
}
250
274
}
251
275
252
- public static void freeMemoryForOptimization (final long iDelayTime ) {
253
- freeMemory (iDelayTime , OGlobalConfiguration .JVM_GC_DELAY_FOR_OPTIMIZE .getValueAsLong ());
254
- }
255
-
256
- public static void freeMemoryForResourceCleanup (final long iDelayTime ) {
257
- freeMemory (iDelayTime , 0 );
258
- }
259
-
260
276
public long getUsedHeapMemory () {
261
277
MemoryUsage heapMemory = memBean .getHeapMemoryUsage ();
262
278
return heapMemory .getUsed ();
@@ -267,19 +283,10 @@ public int getUsedHeapMemoryInPercentage() {
267
283
return (int ) (heapMemory .getUsed () * 100 / heapMemory .getMax ());
268
284
}
269
285
270
- private static void freeMemory (final long iDelayTime , final long minimalTimeAmount ) {
271
- final long dateLastGC = System .currentTimeMillis ();
272
- if (dateLastGC - lastGC > minimalTimeAmount * 1000 ) {
273
- lastGC = dateLastGC ;
274
- System .gc ();
275
-
276
- if (iDelayTime > 0 )
277
- try {
278
- Thread .sleep (iDelayTime );
279
- } catch (InterruptedException e ) {
280
- Thread .currentThread ().interrupt ();
281
- }
286
+ public void sendShutdown () {
287
+ interrupt ();
288
+ synchronized (monitorQueue ) {
289
+ monitorQueue .notifyAll ();
282
290
}
283
291
}
284
-
285
292
}
0 commit comments