src/share/vm/services/lowMemoryDetector.cpp

Wed, 27 Aug 2014 08:19:12 -0400

author
zgu
date
Wed, 27 Aug 2014 08:19:12 -0400
changeset 7074
833b0f92429a
parent 6680
78bbf4d43a14
child 6876
710a3c8b516e
child 8876
8a9294fa59d6
permissions
-rw-r--r--

8046598: Scalable Native memory tracking development
Summary: Enhance scalability of native memory tracking
Reviewed-by: coleenp, ctornqvi, gtriantafill

duke@435 1 /*
drchase@6680 2 * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
stefank@2314 25 #include "precompiled.hpp"
stefank@2314 26 #include "classfile/systemDictionary.hpp"
stefank@2314 27 #include "classfile/vmSymbols.hpp"
stefank@2314 28 #include "oops/oop.inline.hpp"
stefank@2314 29 #include "runtime/interfaceSupport.hpp"
stefank@2314 30 #include "runtime/java.hpp"
stefank@2314 31 #include "runtime/javaCalls.hpp"
stefank@2314 32 #include "runtime/mutex.hpp"
stefank@2314 33 #include "runtime/mutexLocker.hpp"
stefank@2314 34 #include "services/lowMemoryDetector.hpp"
stefank@2314 35 #include "services/management.hpp"
duke@435 36
duke@435 37 volatile bool LowMemoryDetector::_enabled_for_collected_pools = false;
duke@435 38 volatile jint LowMemoryDetector::_disabled_count = 0;
duke@435 39
duke@435 40 bool LowMemoryDetector::has_pending_requests() {
kamg@2511 41 assert(Service_lock->owned_by_self(), "Must own Service_lock");
duke@435 42 bool has_requests = false;
duke@435 43 int num_memory_pools = MemoryService::num_memory_pools();
duke@435 44 for (int i = 0; i < num_memory_pools; i++) {
duke@435 45 MemoryPool* pool = MemoryService::get_memory_pool(i);
duke@435 46 SensorInfo* sensor = pool->usage_sensor();
duke@435 47 if (sensor != NULL) {
duke@435 48 has_requests = has_requests || sensor->has_pending_requests();
duke@435 49 }
duke@435 50
duke@435 51 SensorInfo* gc_sensor = pool->gc_usage_sensor();
duke@435 52 if (gc_sensor != NULL) {
duke@435 53 has_requests = has_requests || gc_sensor->has_pending_requests();
duke@435 54 }
duke@435 55 }
duke@435 56 return has_requests;
duke@435 57 }
duke@435 58
kamg@2511 59 void LowMemoryDetector::process_sensor_changes(TRAPS) {
kamg@2511 60 ResourceMark rm(THREAD);
kamg@2511 61 HandleMark hm(THREAD);
duke@435 62
kamg@2511 63 // No need to hold Service_lock to call out to Java
kamg@2511 64 int num_memory_pools = MemoryService::num_memory_pools();
kamg@2511 65 for (int i = 0; i < num_memory_pools; i++) {
kamg@2511 66 MemoryPool* pool = MemoryService::get_memory_pool(i);
kamg@2511 67 SensorInfo* sensor = pool->usage_sensor();
kamg@2511 68 SensorInfo* gc_sensor = pool->gc_usage_sensor();
kamg@2511 69 if (sensor != NULL && sensor->has_pending_requests()) {
kamg@2511 70 sensor->process_pending_requests(CHECK);
duke@435 71 }
kamg@2511 72 if (gc_sensor != NULL && gc_sensor->has_pending_requests()) {
kamg@2511 73 gc_sensor->process_pending_requests(CHECK);
duke@435 74 }
duke@435 75 }
duke@435 76 }
duke@435 77
duke@435 78 // This method could be called from any Java threads
duke@435 79 // and also VMThread.
duke@435 80 void LowMemoryDetector::detect_low_memory() {
kamg@2511 81 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
duke@435 82
duke@435 83 bool has_pending_requests = false;
duke@435 84 int num_memory_pools = MemoryService::num_memory_pools();
duke@435 85 for (int i = 0; i < num_memory_pools; i++) {
duke@435 86 MemoryPool* pool = MemoryService::get_memory_pool(i);
duke@435 87 SensorInfo* sensor = pool->usage_sensor();
duke@435 88 if (sensor != NULL &&
duke@435 89 pool->usage_threshold()->is_high_threshold_supported() &&
duke@435 90 pool->usage_threshold()->high_threshold() != 0) {
duke@435 91 MemoryUsage usage = pool->get_memory_usage();
duke@435 92 sensor->set_gauge_sensor_level(usage,
duke@435 93 pool->usage_threshold());
duke@435 94 has_pending_requests = has_pending_requests || sensor->has_pending_requests();
duke@435 95 }
duke@435 96 }
duke@435 97
duke@435 98 if (has_pending_requests) {
kamg@2511 99 Service_lock->notify_all();
duke@435 100 }
duke@435 101 }
duke@435 102
duke@435 103 // This method could be called from any Java threads
duke@435 104 // and also VMThread.
duke@435 105 void LowMemoryDetector::detect_low_memory(MemoryPool* pool) {
duke@435 106 SensorInfo* sensor = pool->usage_sensor();
duke@435 107 if (sensor == NULL ||
duke@435 108 !pool->usage_threshold()->is_high_threshold_supported() ||
duke@435 109 pool->usage_threshold()->high_threshold() == 0) {
duke@435 110 return;
duke@435 111 }
duke@435 112
duke@435 113 {
kamg@2511 114 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
duke@435 115
duke@435 116 MemoryUsage usage = pool->get_memory_usage();
duke@435 117 sensor->set_gauge_sensor_level(usage,
duke@435 118 pool->usage_threshold());
duke@435 119 if (sensor->has_pending_requests()) {
duke@435 120 // notify sensor state update
kamg@2511 121 Service_lock->notify_all();
duke@435 122 }
duke@435 123 }
duke@435 124 }
duke@435 125
duke@435 126 // Only called by VMThread at GC time
duke@435 127 void LowMemoryDetector::detect_after_gc_memory(MemoryPool* pool) {
duke@435 128 SensorInfo* sensor = pool->gc_usage_sensor();
duke@435 129 if (sensor == NULL ||
duke@435 130 !pool->gc_usage_threshold()->is_high_threshold_supported() ||
duke@435 131 pool->gc_usage_threshold()->high_threshold() == 0) {
duke@435 132 return;
duke@435 133 }
duke@435 134
duke@435 135 {
kamg@2511 136 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
duke@435 137
duke@435 138 MemoryUsage usage = pool->get_last_collection_usage();
duke@435 139 sensor->set_counter_sensor_level(usage, pool->gc_usage_threshold());
duke@435 140
duke@435 141 if (sensor->has_pending_requests()) {
duke@435 142 // notify sensor state update
kamg@2511 143 Service_lock->notify_all();
duke@435 144 }
duke@435 145 }
duke@435 146 }
duke@435 147
duke@435 148 // recompute enabled flag
duke@435 149 void LowMemoryDetector::recompute_enabled_for_collected_pools() {
duke@435 150 bool enabled = false;
duke@435 151 int num_memory_pools = MemoryService::num_memory_pools();
duke@435 152 for (int i=0; i<num_memory_pools; i++) {
duke@435 153 MemoryPool* pool = MemoryService::get_memory_pool(i);
duke@435 154 if (pool->is_collected_pool() && is_enabled(pool)) {
duke@435 155 enabled = true;
duke@435 156 break;
duke@435 157 }
duke@435 158 }
duke@435 159 _enabled_for_collected_pools = enabled;
duke@435 160 }
duke@435 161
duke@435 162 SensorInfo::SensorInfo() {
duke@435 163 _sensor_obj = NULL;
duke@435 164 _sensor_on = false;
duke@435 165 _sensor_count = 0;
duke@435 166 _pending_trigger_count = 0;
duke@435 167 _pending_clear_count = 0;
duke@435 168 }
duke@435 169
duke@435 170 // When this method is used, the memory usage is monitored
duke@435 171 // as a gauge attribute. Sensor notifications (trigger or
duke@435 172 // clear) is only emitted at the first time it crosses
duke@435 173 // a threshold.
duke@435 174 //
duke@435 175 // High and low thresholds are designed to provide a
duke@435 176 // hysteresis mechanism to avoid repeated triggering
duke@435 177 // of notifications when the attribute value makes small oscillations
duke@435 178 // around the high or low threshold value.
duke@435 179 //
duke@435 180 // The sensor will be triggered if:
duke@435 181 // (1) the usage is crossing above the high threshold and
duke@435 182 // the sensor is currently off and no pending
duke@435 183 // trigger requests; or
duke@435 184 // (2) the usage is crossing above the high threshold and
duke@435 185 // the sensor will be off (i.e. sensor is currently on
duke@435 186 // and has pending clear requests).
duke@435 187 //
duke@435 188 // Subsequent crossings of the high threshold value do not cause
duke@435 189 // any triggers unless the usage becomes less than the low threshold.
duke@435 190 //
duke@435 191 // The sensor will be cleared if:
duke@435 192 // (1) the usage is crossing below the low threshold and
duke@435 193 // the sensor is currently on and no pending
duke@435 194 // clear requests; or
duke@435 195 // (2) the usage is crossing below the low threshold and
duke@435 196 // the sensor will be on (i.e. sensor is currently off
duke@435 197 // and has pending trigger requests).
duke@435 198 //
duke@435 199 // Subsequent crossings of the low threshold value do not cause
duke@435 200 // any clears unless the usage becomes greater than or equal
duke@435 201 // to the high threshold.
duke@435 202 //
duke@435 203 // If the current level is between high and low threhsold, no change.
duke@435 204 //
duke@435 205 void SensorInfo::set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold) {
duke@435 206 assert(high_low_threshold->is_high_threshold_supported(), "just checking");
duke@435 207
duke@435 208 bool is_over_high = high_low_threshold->is_high_threshold_crossed(usage);
duke@435 209 bool is_below_low = high_low_threshold->is_low_threshold_crossed(usage);
duke@435 210
duke@435 211 assert(!(is_over_high && is_below_low), "Can't be both true");
duke@435 212
duke@435 213 if (is_over_high &&
duke@435 214 ((!_sensor_on && _pending_trigger_count == 0) ||
duke@435 215 _pending_clear_count > 0)) {
duke@435 216 // low memory detected and need to increment the trigger pending count
duke@435 217 // if the sensor is off or will be off due to _pending_clear_ > 0
duke@435 218 // Request to trigger the sensor
duke@435 219 _pending_trigger_count++;
duke@435 220 _usage = usage;
duke@435 221
duke@435 222 if (_pending_clear_count > 0) {
duke@435 223 // non-zero pending clear requests indicates that there are
duke@435 224 // pending requests to clear this sensor.
duke@435 225 // This trigger request needs to clear this clear count
duke@435 226 // since the resulting sensor flag should be on.
duke@435 227 _pending_clear_count = 0;
duke@435 228 }
duke@435 229 } else if (is_below_low &&
duke@435 230 ((_sensor_on && _pending_clear_count == 0) ||
duke@435 231 (_pending_trigger_count > 0 && _pending_clear_count == 0))) {
duke@435 232 // memory usage returns below the threshold
duke@435 233 // Request to clear the sensor if the sensor is on or will be on due to
duke@435 234 // _pending_trigger_count > 0 and also no clear request
duke@435 235 _pending_clear_count++;
duke@435 236 }
duke@435 237 }
duke@435 238
duke@435 239 // When this method is used, the memory usage is monitored as a
duke@435 240 // simple counter attribute. The sensor will be triggered
duke@435 241 // whenever the usage is crossing the threshold to keep track
duke@435 242 // of the number of times the VM detects such a condition occurs.
duke@435 243 //
duke@435 244 // High and low thresholds are designed to provide a
duke@435 245 // hysteresis mechanism to avoid repeated triggering
duke@435 246 // of notifications when the attribute value makes small oscillations
duke@435 247 // around the high or low threshold value.
duke@435 248 //
duke@435 249 // The sensor will be triggered if:
duke@435 250 // - the usage is crossing above the high threshold regardless
duke@435 251 // of the current sensor state.
duke@435 252 //
duke@435 253 // The sensor will be cleared if:
duke@435 254 // (1) the usage is crossing below the low threshold and
duke@435 255 // the sensor is currently on; or
duke@435 256 // (2) the usage is crossing below the low threshold and
duke@435 257 // the sensor will be on (i.e. sensor is currently off
duke@435 258 // and has pending trigger requests).
duke@435 259 void SensorInfo::set_counter_sensor_level(MemoryUsage usage, ThresholdSupport* counter_threshold) {
duke@435 260 assert(counter_threshold->is_high_threshold_supported(), "just checking");
duke@435 261
duke@435 262 bool is_over_high = counter_threshold->is_high_threshold_crossed(usage);
duke@435 263 bool is_below_low = counter_threshold->is_low_threshold_crossed(usage);
duke@435 264
duke@435 265 assert(!(is_over_high && is_below_low), "Can't be both true");
duke@435 266
duke@435 267 if (is_over_high) {
duke@435 268 _pending_trigger_count++;
duke@435 269 _usage = usage;
duke@435 270 _pending_clear_count = 0;
duke@435 271 } else if (is_below_low && (_sensor_on || _pending_trigger_count > 0)) {
duke@435 272 _pending_clear_count++;
duke@435 273 }
duke@435 274 }
duke@435 275
duke@435 276 void SensorInfo::oops_do(OopClosure* f) {
duke@435 277 f->do_oop((oop*) &_sensor_obj);
duke@435 278 }
duke@435 279
duke@435 280 void SensorInfo::process_pending_requests(TRAPS) {
duke@435 281 if (!has_pending_requests()) {
duke@435 282 return;
duke@435 283 }
duke@435 284
duke@435 285 int pending_count = pending_trigger_count();
duke@435 286 if (pending_clear_count() > 0) {
duke@435 287 clear(pending_count, CHECK);
duke@435 288 } else {
duke@435 289 trigger(pending_count, CHECK);
duke@435 290 }
duke@435 291
duke@435 292 }
duke@435 293
duke@435 294 void SensorInfo::trigger(int count, TRAPS) {
duke@435 295 assert(count <= _pending_trigger_count, "just checking");
duke@435 296
duke@435 297 if (_sensor_obj != NULL) {
coleenp@4037 298 Klass* k = Management::sun_management_Sensor_klass(CHECK);
duke@435 299 instanceKlassHandle sensorKlass (THREAD, k);
duke@435 300 Handle sensor_h(THREAD, _sensor_obj);
duke@435 301 Handle usage_h = MemoryService::create_MemoryUsage_obj(_usage, CHECK);
duke@435 302
duke@435 303 JavaValue result(T_VOID);
duke@435 304 JavaCallArguments args(sensor_h);
duke@435 305 args.push_int((int) count);
duke@435 306 args.push_oop(usage_h);
duke@435 307
duke@435 308 JavaCalls::call_virtual(&result,
duke@435 309 sensorKlass,
coleenp@2497 310 vmSymbols::trigger_name(),
coleenp@2497 311 vmSymbols::trigger_method_signature(),
duke@435 312 &args,
duke@435 313 CHECK);
duke@435 314 }
duke@435 315
duke@435 316 {
kamg@2511 317 // Holds Service_lock and update the sensor state
kamg@2511 318 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
duke@435 319 _sensor_on = true;
duke@435 320 _sensor_count += count;
duke@435 321 _pending_trigger_count = _pending_trigger_count - count;
duke@435 322 }
duke@435 323 }
duke@435 324
duke@435 325 void SensorInfo::clear(int count, TRAPS) {
duke@435 326 if (_sensor_obj != NULL) {
coleenp@4037 327 Klass* k = Management::sun_management_Sensor_klass(CHECK);
duke@435 328 instanceKlassHandle sensorKlass (THREAD, k);
duke@435 329 Handle sensor(THREAD, _sensor_obj);
duke@435 330
duke@435 331 JavaValue result(T_VOID);
duke@435 332 JavaCallArguments args(sensor);
duke@435 333 args.push_int((int) count);
duke@435 334 JavaCalls::call_virtual(&result,
duke@435 335 sensorKlass,
coleenp@2497 336 vmSymbols::clear_name(),
coleenp@2497 337 vmSymbols::int_void_signature(),
duke@435 338 &args,
duke@435 339 CHECK);
duke@435 340 }
duke@435 341
duke@435 342 {
kamg@2511 343 // Holds Service_lock and update the sensor state
kamg@2511 344 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
duke@435 345 _sensor_on = false;
duke@435 346 _pending_clear_count = 0;
duke@435 347 _pending_trigger_count = _pending_trigger_count - count;
duke@435 348 }
duke@435 349 }
duke@435 350
duke@435 351 //--------------------------------------------------------------
duke@435 352 // Non-product code
duke@435 353
duke@435 354 #ifndef PRODUCT
duke@435 355 void SensorInfo::print() {
drchase@6680 356 tty->print_cr("%s count = " SIZE_FORMAT " pending_triggers = %d pending_clears = %d",
duke@435 357 (_sensor_on ? "on" : "off"),
duke@435 358 _sensor_count, _pending_trigger_count, _pending_clear_count);
duke@435 359 }
duke@435 360
duke@435 361 #endif // PRODUCT

mercurial