src/share/vm/services/lowMemoryDetector.hpp

changeset 0
f90c822e73f8
child 6876
710a3c8b516e
equal deleted inserted replaced
-1:000000000000 0:f90c822e73f8
1 /*
2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_VM_SERVICES_LOWMEMORYDETECTOR_HPP
26 #define SHARE_VM_SERVICES_LOWMEMORYDETECTOR_HPP
27
28 #include "memory/allocation.hpp"
29 #include "services/memoryPool.hpp"
30 #include "services/memoryService.hpp"
31
32 // Low Memory Detection Support
33 // Two memory alarms in the JDK (we called them sensors).
34 // - Heap memory sensor
35 // - Non-heap memory sensor
36 // When the VM detects if the memory usage of a memory pool has reached
37 // or exceeded its threshold, it will trigger the sensor for the type
38 // of the memory pool (heap or nonheap or both).
39 //
40 // If threshold == -1, no low memory detection is supported and
41 // the threshold value is not allowed to be changed.
42 // If threshold == 0, no low memory detection is performed for
43 // that memory pool. The threshold can be set to any non-negative
44 // value.
45 //
46 // The default threshold of the Hotspot memory pools are:
47 // Eden space -1
48 // Survivor space 1 -1
49 // Survivor space 2 -1
50 // Old generation 0
51 // Perm generation 0
52 // CodeCache 0
53 //
54 // For heap memory, detection will be performed when GC finishes
55 // and also in the slow path allocation.
56 // For Code cache, detection will be performed in the allocation
57 // and deallocation.
58 //
59 // May need to deal with hysteresis effect.
60 //
61 // Memory detection code runs in the Service thread (serviceThread.hpp).
62
63 class OopClosure;
64 class MemoryPool;
65
66 class ThresholdSupport : public CHeapObj<mtInternal> {
67 private:
68 bool _support_high_threshold;
69 bool _support_low_threshold;
70 size_t _high_threshold;
71 size_t _low_threshold;
72 public:
73 ThresholdSupport(bool support_high, bool support_low) {
74 _support_high_threshold = support_high;
75 _support_low_threshold = support_low;
76 _high_threshold = 0;
77 _low_threshold= 0;
78 }
79
80 size_t high_threshold() const { return _high_threshold; }
81 size_t low_threshold() const { return _low_threshold; }
82 bool is_high_threshold_supported() { return _support_high_threshold; }
83 bool is_low_threshold_supported() { return _support_low_threshold; }
84
85 bool is_high_threshold_crossed(MemoryUsage usage) {
86 if (_support_high_threshold && _high_threshold > 0) {
87 return (usage.used() >= _high_threshold);
88 }
89 return false;
90 }
91 bool is_low_threshold_crossed(MemoryUsage usage) {
92 if (_support_low_threshold && _low_threshold > 0) {
93 return (usage.used() < _low_threshold);
94 }
95 return false;
96 }
97
98 size_t set_high_threshold(size_t new_threshold) {
99 assert(_support_high_threshold, "can only be set if supported");
100 assert(new_threshold >= _low_threshold, "new_threshold must be >= _low_threshold");
101 size_t prev = _high_threshold;
102 _high_threshold = new_threshold;
103 return prev;
104 }
105
106 size_t set_low_threshold(size_t new_threshold) {
107 assert(_support_low_threshold, "can only be set if supported");
108 assert(new_threshold <= _high_threshold, "new_threshold must be <= _high_threshold");
109 size_t prev = _low_threshold;
110 _low_threshold = new_threshold;
111 return prev;
112 }
113 };
114
115 class SensorInfo : public CHeapObj<mtInternal> {
116 private:
117 instanceOop _sensor_obj;
118 bool _sensor_on;
119 size_t _sensor_count;
120
121 // before the actual sensor on flag and sensor count are set
122 // we maintain the number of pending triggers and clears.
123 // _pending_trigger_count means the number of pending triggers
124 // and the sensor count should be incremented by the same number.
125
126 int _pending_trigger_count;
127
128 // _pending_clear_count takes precedence if it's > 0 which
129 // indicates the resulting sensor will be off
130 // Sensor trigger requests will reset this clear count to
131 // indicate the resulting flag should be on.
132
133 int _pending_clear_count;
134
135 MemoryUsage _usage;
136
137 void clear(int count, TRAPS);
138 void trigger(int count, TRAPS);
139 public:
140 SensorInfo();
141 void set_sensor(instanceOop sensor) {
142 assert(_sensor_obj == NULL, "Should be set only once");
143 _sensor_obj = sensor;
144 }
145
146 bool has_pending_requests() {
147 return (_pending_trigger_count > 0 || _pending_clear_count > 0);
148 }
149
150 int pending_trigger_count() { return _pending_trigger_count; }
151 int pending_clear_count() { return _pending_clear_count; }
152
153 // When this method is used, the memory usage is monitored
154 // as a gauge attribute. High and low thresholds are designed
155 // to provide a hysteresis mechanism to avoid repeated triggering
156 // of notifications when the attribute value makes small oscillations
157 // around the high or low threshold value.
158 //
159 // The sensor will be triggered if:
160 // (1) the usage is crossing above the high threshold and
161 // the sensor is currently off and no pending
162 // trigger requests; or
163 // (2) the usage is crossing above the high threshold and
164 // the sensor will be off (i.e. sensor is currently on
165 // and has pending clear requests).
166 //
167 // Subsequent crossings of the high threshold value do not cause
168 // any triggers unless the usage becomes less than the low threshold.
169 //
170 // The sensor will be cleared if:
171 // (1) the usage is crossing below the low threshold and
172 // the sensor is currently on and no pending
173 // clear requests; or
174 // (2) the usage is crossing below the low threshold and
175 // the sensor will be on (i.e. sensor is currently off
176 // and has pending trigger requests).
177 //
178 // Subsequent crossings of the low threshold value do not cause
179 // any clears unless the usage becomes greater than or equal
180 // to the high threshold.
181 //
182 // If the current level is between high and low threhsold, no change.
183 //
184 void set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold);
185
186 // When this method is used, the memory usage is monitored as a
187 // simple counter attribute. The sensor will be triggered
188 // whenever the usage is crossing the threshold to keep track
189 // of the number of times the VM detects such a condition occurs.
190 //
191 // The sensor will be triggered if:
192 // - the usage is crossing above the high threshold regardless
193 // of the current sensor state.
194 //
195 // The sensor will be cleared if:
196 // (1) the usage is crossing below the low threshold and
197 // the sensor is currently on; or
198 // (2) the usage is crossing below the low threshold and
199 // the sensor will be on (i.e. sensor is currently off
200 // and has pending trigger requests).
201 //
202 void set_counter_sensor_level(MemoryUsage usage, ThresholdSupport* counter_threshold);
203
204 void process_pending_requests(TRAPS);
205 void oops_do(OopClosure* f);
206
207 #ifndef PRODUCT
208 // printing on default output stream;
209 void print();
210 #endif // PRODUCT
211 };
212
213 class LowMemoryDetector : public AllStatic {
214 friend class LowMemoryDetectorDisabler;
215 friend class ServiceThread;
216 private:
217 // true if any collected heap has low memory detection enabled
218 static volatile bool _enabled_for_collected_pools;
219 // > 0 if temporary disabed
220 static volatile jint _disabled_count;
221
222 static void check_memory_usage();
223 static bool has_pending_requests();
224 static bool temporary_disabled() { return _disabled_count > 0; }
225 static void disable() { Atomic::inc(&_disabled_count); }
226 static void enable() { Atomic::dec(&_disabled_count); }
227 static void process_sensor_changes(TRAPS);
228
229 public:
230 static void detect_low_memory();
231 static void detect_low_memory(MemoryPool* pool);
232 static void detect_after_gc_memory(MemoryPool* pool);
233
234 static bool is_enabled(MemoryPool* pool) {
235 // low memory detection is enabled for collected memory pools
236 // iff one of the collected memory pool has a sensor and the
237 // threshold set non-zero
238 if (pool->usage_sensor() == NULL) {
239 return false;
240 } else {
241 ThresholdSupport* threshold_support = pool->usage_threshold();
242 return (threshold_support->is_high_threshold_supported() ?
243 (threshold_support->high_threshold() > 0) : false);
244 }
245 }
246
247 // indicates if low memory detection is enabled for any collected
248 // memory pools
249 static inline bool is_enabled_for_collected_pools() {
250 return !temporary_disabled() && _enabled_for_collected_pools;
251 }
252
253 // recompute enabled flag
254 static void recompute_enabled_for_collected_pools();
255
256 // low memory detection for collected memory pools.
257 static inline void detect_low_memory_for_collected_pools() {
258 // no-op if low memory detection not enabled
259 if (!is_enabled_for_collected_pools()) {
260 return;
261 }
262 int num_memory_pools = MemoryService::num_memory_pools();
263 for (int i=0; i<num_memory_pools; i++) {
264 MemoryPool* pool = MemoryService::get_memory_pool(i);
265
266 // if low memory detection is enabled then check if the
267 // current used exceeds the high threshold
268 if (pool->is_collected_pool() && is_enabled(pool)) {
269 size_t used = pool->used_in_bytes();
270 size_t high = pool->usage_threshold()->high_threshold();
271 if (used > high) {
272 detect_low_memory(pool);
273 }
274 }
275 }
276 }
277 };
278
279 class LowMemoryDetectorDisabler: public StackObj {
280 public:
281 LowMemoryDetectorDisabler()
282 {
283 LowMemoryDetector::disable();
284 }
285 ~LowMemoryDetectorDisabler()
286 {
287 assert(LowMemoryDetector::temporary_disabled(), "should be disabled!");
288 LowMemoryDetector::enable();
289 }
290 };
291
292 #endif // SHARE_VM_SERVICES_LOWMEMORYDETECTOR_HPP

mercurial