rev 57625 : [mq]: metaspace-improvement
1 /* 2 * Copyright (c) 2018, 2019, 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 #include "precompiled.hpp" 25 26 27 #include "logging/log.hpp" 28 #include "memory/metaspace/constants.hpp" 29 #include "memory/metaspace/chunkAllocSequence.hpp" 30 #include "memory/metaspace/chunkLevel.hpp" 31 #include "memory/metaspace/chunkManager.hpp" 32 #include "memory/metaspace/metachunk.hpp" 33 #include "memory/metaspace/metaspaceStatistics.hpp" 34 #include "memory/metaspace/virtualSpaceNode.hpp" 35 #include "memory/metaspace/virtualSpaceList.hpp" 36 #include "runtime/mutexLocker.hpp" 37 #include "utilities/debug.hpp" 38 #include "utilities/globalDefinitions.hpp" 39 40 namespace metaspace { 41 42 43 // Return a single chunk to the freelist and adjust accounting. No merge is attempted. 44 void ChunkManager::return_chunk_simple(Metachunk* c) { 45 46 assert_lock_strong(MetaspaceExpand_lock); 47 48 DEBUG_ONLY(c->verify(false)); 49 50 const chklvl_t lvl = c->level(); 51 _chunks[lvl].add(c); 52 _total_word_size.increment_by(c->word_size()); 53 _committed_word_size.increment_by(c->committed_words()); 54 55 // Tracing 56 log_debug(metaspace)("ChunkManager %s: returned chunk " PTR_FORMAT ", level " CHKLVL_FORMAT, 57 _name, p2i(c), c->level()); 58 59 } 60 61 // Take a single chunk from the given freelist and adjust counters. Returns NULL 62 // if there is no fitting chunk for this level. 63 Metachunk* ChunkManager::remove_first_chunk_at_level(chklvl_t l) { 64 65 assert_lock_strong(MetaspaceExpand_lock); 66 DEBUG_ONLY(chklvl::check_valid_level(l);) 67 68 Metachunk* c = _chunks[l].remove_first(); 69 if (c != NULL) { 70 _total_word_size.decrement_by(c->word_size()); 71 _committed_word_size.decrement_by(c->committed_words()); 72 } 73 74 // Tracing 75 if (c != NULL) { 76 log_debug(metaspace)("ChunkManager %s: removed chunk " PTR_FORMAT ", level " CHKLVL_FORMAT, 77 _name, p2i(c), c->level()); 78 } else { 79 log_trace(metaspace)("ChunkManager %s: no chunk found for level " CHKLVL_FORMAT, 80 _name, l); 81 } 82 83 return c; 84 } 85 86 // Creates a chunk manager with a given name (which is for debug purposes only) 87 // and an associated space list which will be used to request new chunks from 88 // (see get_chunk()) 89 ChunkManager::ChunkManager(const char* name, VirtualSpaceList* space_list) 90 : _vslist(space_list), 91 _name(name), 92 _chunks() 93 { 94 } 95 96 // Given a chunk we are about to handout to the caller, make sure it is committed 97 // according to constants::committed_words_on_fresh_chunks 98 bool ChunkManager::commit_chunk_before_handout(Metachunk* c) { 99 assert_lock_strong(MetaspaceExpand_lock); 100 const size_t must_be_committed = MIN2(c->word_size(), constants::committed_words_on_fresh_chunks); 101 return c->ensure_committed_locked(must_be_committed); 102 } 103 104 #ifdef ASSERT 105 // Given a splinters array returned from a split operation, check that it meets expectations 106 static void check_splinters_array(Metachunk* splinters[chklvl::NUM_CHUNK_LEVELS], chklvl_t min, chklvl_t max) { 107 // The array shall contain splinters in the range [min, max] and nothing outside. The chunk levels for 108 // the chunks must match too. 109 for (chklvl_t l = chklvl::ROOT_CHUNK_LEVEL; l <= chklvl::HIGHEST_CHUNK_LEVEL; l ++) { 110 if (l >= min && l < max) { 111 assert(splinters[l] != NULL, "Missing splinters"); 112 assert(splinters[l]->level() == l, "Unexpected level"); 113 splinters[l]->verify(false); 114 } else { 115 assert(splinters[l] == NULL, "Unexpected splinters"); 116 } 117 } 118 } 119 #endif 120 121 122 // Given a chunk which must be outside of a freelist and must be free, split it to 123 // meet a target level and return it. Splinters are added to the freelist. 124 Metachunk* ChunkManager::split_chunk_and_add_splinters(Metachunk* c, chklvl_t target_level) { 125 126 assert_lock_strong(MetaspaceExpand_lock); 127 128 assert(c->is_free() && c->level() < target_level, "Invalid chunk for splitting"); 129 DEBUG_ONLY(chklvl::check_valid_level(target_level);) 130 131 // Chunk must be outside of our freelists 132 assert(_chunks[c->level()].contains(c) == false, "Chunk is in freelist."); 133 134 log_debug(metaspace)("ChunkManager %s: chunk " PTR_FORMAT ", level " CHKLVL_FORMAT 135 ": split to " CHKLVL_FORMAT ".", 136 _name, p2i(c), c->level(), target_level); 137 138 const chklvl_t orig_level = c->level(); 139 Metachunk* splinters[chklvl::NUM_CHUNK_LEVELS] = { 0 }; 140 c = c->vsnode()->split(target_level, c, splinters); 141 142 // Splitting should never fail. 143 assert(c != NULL, "Split failed"); 144 assert(c->level() == target_level, "Sanity"); 145 DEBUG_ONLY(c->verify(false)); 146 DEBUG_ONLY(check_splinters_array(splinters, orig_level + 1, target_level);) 147 148 // Return splinters to freelist. 149 for (chklvl_t l = orig_level + 1; l <= target_level; l ++) { 150 log_trace(metaspace)("ChunkManager %s: return splinter chunk " PTR_FORMAT ", level " CHKLVL_FORMAT ".", 151 _name, p2i(c), c->level()); 152 return_chunk_simple(splinters[l]); 153 } 154 155 return c; 156 } 157 158 // Get a chunk and be smart about it. 159 // - 1) Attempt to find a free chunk of exactly the pref_level level 160 // - 2) Failing that, attempt to find a chunk smaller or equal the minimal level. 161 // - 3) Failing that, attempt to find a free chunk of larger size and split it. 162 // - 4) Failing that, attempt to allocate a new chunk from the connected virtual space. 163 // - Failing that, give up and return NULL. 164 // Note: this is not guaranteed to return a *committed* chunk. The chunk manager will 165 // attempt to commit the returned chunk according to constants::committed_words_on_fresh_chunks; 166 // but this may fail if we hit a commit limit. In that case, a partly uncommit chunk 167 // will be returned, and the commit is attempted again when we allocate from the chunk's 168 // uncommitted area. See also Metachunk::allocate. 169 Metachunk* ChunkManager::get_chunk(chklvl_t min_level, chklvl_t pref_level) { 170 171 MutexLocker fcl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag); 172 173 DEBUG_ONLY(chklvl::check_valid_level(min_level);) 174 DEBUG_ONLY(chklvl::check_valid_level(pref_level);) 175 176 Metachunk* c = NULL; 177 178 // Tracing 179 log_debug(metaspace)("ChunkManager %s: get chunk: min " CHKLVL_FORMAT ", preferred " CHKLVL_FORMAT ".", 180 _name, min_level, pref_level); 181 182 // 1) Attempt to find a free chunk of exactly the pref_level level 183 c = remove_first_chunk_at_level(pref_level); 184 185 // 2) Failing that, attempt to find a chunk smaller or equal the minimal level. 186 if (c == NULL) { 187 for (chklvl_t lvl = pref_level + 1; lvl <= min_level; lvl ++) { 188 c = remove_first_chunk_at_level(lvl); 189 if (c != NULL) { 190 break; 191 } 192 } 193 } 194 195 // 3) Failing that, attempt to find a free chunk of larger size and split it. 196 if (c == NULL) { 197 for (chklvl_t lvl = pref_level - 1; lvl >= chklvl::ROOT_CHUNK_LEVEL; lvl --) { 198 c = remove_first_chunk_at_level(lvl); 199 if (c != NULL) { 200 // Split chunk; add splinters to freelist 201 c = split_chunk_and_add_splinters(c, pref_level); 202 break; 203 } 204 } 205 } 206 207 // 4) Failing that, attempt to allocate a new chunk from the connected virtual space. 208 if (c == NULL) { 209 210 // Tracing 211 log_debug(metaspace)("ChunkManager %s: need new root chunk.", _name); 212 213 c = _vslist->allocate_root_chunk(); 214 215 // This should always work. Note that getting the root chunk may not mean we committed memory. 216 assert(c != NULL, "Unexpected"); 217 assert(c->level() == chklvl::LOWEST_CHUNK_LEVEL, "Not a root chunk?"); 218 219 // Split this root chunk to the desired chunk size. 220 if (pref_level > c->level()) { 221 c = split_chunk_and_add_splinters(c, pref_level); 222 } 223 } 224 225 // Note that we should at this point have a chunk; should always work. If we hit 226 // a commit limit in the meantime, the chunk may still be uncommitted, but the chunk 227 // itself should exist now. 228 assert(c != NULL, "Unexpected"); 229 230 // Before returning the chunk, attempt to commit it according to the handout rules. 231 // If that fails, we ignore the error and return the uncommitted chunk. 232 if (commit_chunk_before_handout(c) == false) { 233 log_info(gc, metaspace)("Failed to commit chunk prior to handout."); 234 } 235 236 DEBUG_ONLY(verify_locked(false);) 237 238 log_debug(metaspace)("ChunkManager %s: handing out chunk " PTR_FORMAT ", level " CHKLVL_FORMAT ".", 239 _name, p2i(c), c->level()); 240 241 return c; 242 243 } // ChunkManager::get_chunk 244 245 246 // Return a single chunk to the ChunkManager and adjust accounting. May merge chunk 247 // with neighbors. 248 // Happens after a Classloader was unloaded and releases its metaspace chunks. 249 // !! Note: this may invalidate the chunk. Do not access the chunk after 250 // this function returns !! 251 void ChunkManager::return_chunk(Metachunk* c) { 252 253 MutexLocker fcl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag); 254 255 DEBUG_ONLY(c->verify(false);) 256 257 log_debug(metaspace)("ChunkManager %s: returning chunk " PTR_FORMAT ", level " CHKLVL_FORMAT ".", 258 _name, p2i(c), c->level()); 259 260 const chklvl_t orig_lvl = c->level(); 261 262 int num_merged[chklvl::NUM_CHUNK_LEVELS] = { 0 }; 263 Metachunk* c2 = c->vsnode()->merge(c, num_merged); 264 265 if (c2 != NULL) { 266 DEBUG_ONLY(c2->verify(false)); 267 268 // We did merge chunks and now have a bigger chunk. 269 assert(c2->level() < orig_lvl, "Sanity"); 270 271 // Adjust counters - the merged-in chunks have been removed from the free lists, but the counters 272 // in this chunk manager must be adjusted too. 273 size_t size_chunks_removed = 0; 274 for (chklvl_t l = chklvl::ROOT_CHUNK_LEVEL; l <= chklvl::HIGHEST_CHUNK_LEVEL; l ++) { 275 if (num_merged[l] > 0) { 276 // Since we have a binary tree, we should exactly see one merge per level. 277 assert(num_merged[l] == 1, "sanity"); 278 _chunks[l].dec_counter_by(1); 279 size_chunks_removed += chklvl::word_size_for_level(l); 280 } 281 } 282 _total_word_size.decrement_by(size_chunks_removed); 283 284 c = c2; 285 } 286 287 return_chunk_simple(c); 288 289 DEBUG_ONLY(verify_locked(false);) 290 291 } 292 293 294 ChunkManager* ChunkManager::_chunkmanager_class = NULL; 295 ChunkManager* ChunkManager::_chunkmanager_nonclass = NULL; 296 297 void ChunkManager::set_chunkmanager_class(ChunkManager* cm) { 298 assert(_chunkmanager_class == NULL, "Sanity"); 299 _chunkmanager_class = cm; 300 } 301 302 void ChunkManager::set_chunkmanager_nonclass(ChunkManager* cm) { 303 assert(_chunkmanager_nonclass == NULL, "Sanity"); 304 _chunkmanager_nonclass = cm; 305 } 306 307 308 // Update statistics. 309 void ChunkManager::add_to_statistics(ChunkManagerStatistics* out) const { 310 311 MutexLocker fcl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag); 312 313 for (chklvl_t l = chklvl::ROOT_CHUNK_LEVEL; l <= chklvl::HIGHEST_CHUNK_LEVEL; l ++) { 314 out->num_chunks[l] += _chunks[l].size(); 315 } 316 317 } 318 319 #ifdef ASSERT 320 321 void ChunkManager::verify(bool slow) const { 322 MutexLocker fcl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag); 323 verify_locked(slow); 324 } 325 326 void ChunkManager::verify_locked(bool slow) const { 327 328 assert_lock_strong(MetaspaceExpand_lock); 329 330 size_t word_size = 0; 331 size_t committed_word_size = 0; 332 for (chklvl_t l = chklvl::LOWEST_CHUNK_LEVEL; 333 l <= chklvl::HIGHEST_CHUNK_LEVEL; l ++) 334 { 335 const Metachunk* c = _chunks[l].first(); 336 int num = 0; 337 while (c) { 338 assert(c->level() == l, "Wrong level"); 339 assert(c->is_free(), "Chunk is not free."); 340 num ++; 341 committed_word_size += c->committed_words(); 342 c->verify(slow); 343 c = c->next(); 344 } 345 assert(num == _chunks[l].size(), "Sanity"); 346 word_size += num * chklvl::word_size_for_level(l); 347 } 348 _total_word_size.check(word_size); 349 _committed_word_size.check(committed_word_size); 350 351 } 352 353 #endif // ASSERT 354 355 356 } // namespace metaspace 357 358 359 --- EOF ---