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 ---