< prev index next >

src/hotspot/share/memory/metaspace/spaceManager.hpp

Print this page
rev 57511 : [mq]: metaspace-improvement

@@ -26,208 +26,100 @@
 #define SHARE_MEMORY_METASPACE_SPACEMANAGER_HPP
 
 #include "memory/allocation.hpp"
 #include "memory/metaspace.hpp"
 #include "memory/metaspace/blockFreelist.hpp"
-#include "memory/metaspace/metaspaceCommon.hpp"
+#include "memory/metaspace/chunkAllocSequence.hpp"
+#include "memory/metaspace/chunkManager.hpp"
 #include "memory/metaspace/metachunk.hpp"
-#include "memory/metaspace/metaspaceStatistics.hpp"
-#include "utilities/debug.hpp"
-#include "utilities/globalDefinitions.hpp"
+#include "memory/metaspace/metaspaceCommon.hpp"
 
 class outputStream;
 class Mutex;
 
 namespace metaspace {
 
-//  SpaceManager - used by Metaspace to handle allocations
-class SpaceManager : public CHeapObj<mtClass> {
-  friend class ::ClassLoaderMetaspace;
-  friend class Metadebug;
+class SpaceManagerStatistics;
 
- private:
+// The SpaceManager:
+// - keeps a list of chunks-in-use by the class loader, as well as a current chunk used
+//   to allocate from
+// - keeps a dictionary of free MetaBlocks. Those can be remnants of a retired chunk or
+//   allocations which were not needed anymore for some reason (e.g. releasing half-allocated
+//   structures when class loading fails)
 
-  // protects allocations
+class SpaceManager : public CHeapObj<mtClass> {
+
+  // Lock handed down from the associated ClassLoaderData.
+  //  Protects allocations from this space.
   Mutex* const _lock;
 
-  // Type of metadata allocated.
-  const Metaspace::MetadataType   _mdtype;
+  // The chunk manager to allocate chunks from.
+  ChunkManager* const _chunk_manager;
 
-  // Type of metaspace
-  const Metaspace::MetaspaceType  _space_type;
+  // The chunk allocation strategy to use.
+  const ChunkAllocSequence* const _chunk_alloc_sequence;
 
   // List of chunks in use by this SpaceManager.  Allocations
   // are done from the current chunk.  The list is used for deallocating
   // chunks when the SpaceManager is freed.
-  Metachunk* _chunk_list;
+  MetachunkList _chunks;
   Metachunk* _current_chunk;
 
-  enum {
-
-    // Maximum number of small chunks to allocate to a SpaceManager
-    small_chunk_limit = 4,
+  // Prematurely released metablocks.
+  BlockFreelist* _block_freelist;
 
-    // Maximum number of specialize chunks to allocate for anonymous and delegating
-    // metadata space to a SpaceManager
-    anon_and_delegating_metadata_specialize_chunk_limit = 4,
 
-    allocation_from_dictionary_limit = 4 * K
+  // Statistics
 
-  };
-
-  // Some running counters, but lets keep their number small to not add to much to
-  // the per-classloader footprint.
+  // Running counters.
   // Note: capacity = used + free + waste + overhead. We do not keep running counters for
   // free and waste. Their sum can be deduced from the three other values.
-  size_t _overhead_words;
-  size_t _capacity_words;
-  size_t _used_words;
-  uintx _num_chunks_by_type[NumberOfInUseLists];
-
-  // Free lists of blocks are per SpaceManager since they
-  // are assumed to be in chunks in use by the SpaceManager
-  // and all chunks in use by a SpaceManager are freed when
-  // the class loader using the SpaceManager is collected.
-  BlockFreelist* _block_freelists;
-
- private:
-  // Accessors
-  Metachunk* chunk_list() const { return _chunk_list; }
-
-  BlockFreelist* block_freelists() const { return _block_freelists; }
-
-  Metaspace::MetadataType mdtype() { return _mdtype; }
+ // size_t _overhead_words;
+  // size_t _capacity_words;
+  // size_t _used_words;
+  uintx _num_chunks_by_level[chklvl::NUM_CHUNK_LEVELS];
+  uintx _num_chunks_total;
 
-  VirtualSpaceList* vs_list()   const { return Metaspace::get_space_list(_mdtype); }
-  ChunkManager* chunk_manager() const { return Metaspace::get_chunk_manager(_mdtype); }
 
-  Metachunk* current_chunk() const { return _current_chunk; }
-  void set_current_chunk(Metachunk* v) {
-    _current_chunk = v;
-  }
+  Mutex* lock() const                           { return _lock; }
+  ChunkManager* chunk_manager() const           { return _chunk_manager; }
+  const ChunkAllocSequence* chunk_alloc_sequence() const    { return _chunk_alloc_sequence; }
 
-  Metachunk* find_current_chunk(size_t word_size);
+  BlockFreelist* block_freelist() const         { return _block_freelist; }
+  void create_block_freelist();
 
-  // Add chunk to the list of chunks in use
-  void add_chunk(Metachunk* v, bool make_current);
+  // The current chunk is unable to service a request. The remainder of the chunk is
+  // chopped into blocks and fed into the _block_freelists, in the hope of later reuse.
   void retire_current_chunk();
 
-  Mutex* lock() const { return _lock; }
+  // Given a requested word size, will allocate a chunk large enough to at least fit that
+  // size, but may be larger according to the rules in the ChunkAllocSequence.
+  // Updates counters and adds the chunk to the head of the chunk list.
+  Metachunk* allocate_chunk_to_fit(size_t requested_word_size);
 
-  // Adds to the given statistic object. Expects to be locked with lock().
-  void add_to_statistics_locked(SpaceManagerStatistics* out) const;
+public:
 
-  // Verify internal counters against the current state. Expects to be locked with lock().
-  DEBUG_ONLY(void verify_metrics_locked() const;)
+  SpaceManager(ChunkManager* chunk_manager, const ChunkAllocSequence* alloc_sequence, Mutex* lock);
 
- public:
-  SpaceManager(Metaspace::MetadataType mdtype,
-               Metaspace::MetaspaceType space_type,
-               Mutex* lock);
   ~SpaceManager();
 
-  enum ChunkMultiples {
-    MediumChunkMultiple = 4
-  };
-
-  static size_t specialized_chunk_size(bool is_class) { return is_class ? ClassSpecializedChunk : SpecializedChunk; }
-  static size_t small_chunk_size(bool is_class)       { return is_class ? ClassSmallChunk : SmallChunk; }
-  static size_t medium_chunk_size(bool is_class)      { return is_class ? ClassMediumChunk : MediumChunk; }
-
-  static size_t smallest_chunk_size(bool is_class)    { return specialized_chunk_size(is_class); }
-
-  // Accessors
-  bool is_class() const { return _mdtype == Metaspace::ClassType; }
-
-  size_t specialized_chunk_size() const { return specialized_chunk_size(is_class()); }
-  size_t small_chunk_size()       const { return small_chunk_size(is_class()); }
-  size_t medium_chunk_size()      const { return medium_chunk_size(is_class()); }
-
-  size_t smallest_chunk_size()    const { return smallest_chunk_size(is_class()); }
-
-  size_t medium_chunk_bunch()     const { return medium_chunk_size() * MediumChunkMultiple; }
-
-  bool is_humongous(size_t word_size) { return word_size > medium_chunk_size(); }
-
-  size_t capacity_words() const     { return _capacity_words; }
-  size_t used_words() const         { return _used_words; }
-  size_t overhead_words() const     { return _overhead_words; }
-
-  // Adjust local, global counters after a new chunk has been added.
-  void account_for_new_chunk(const Metachunk* new_chunk);
-
-  // Adjust local, global counters after space has been allocated from the current chunk.
-  void account_for_allocation(size_t words);
-
-  // Adjust global counters just before the SpaceManager dies, after all its chunks
-  // have been returned to the freelist.
-  void account_for_spacemanager_death();
-
-  // Adjust the initial chunk size to match one of the fixed chunk list sizes,
-  // or return the unadjusted size if the requested size is humongous.
-  static size_t adjust_initial_chunk_size(size_t requested, bool is_class_space);
-  size_t adjust_initial_chunk_size(size_t requested) const;
-
-  // Get the initial chunks size for this metaspace type.
-  size_t get_initial_chunk_size(Metaspace::MetaspaceType type) const;
-
-  // Todo: remove this once we have counters by chunk type.
-  uintx num_chunks_by_type(ChunkIndex chunk_type) const       { return _num_chunks_by_type[chunk_type]; }
-
-  Metachunk* get_new_chunk(size_t chunk_word_size);
-
-  // Block allocation and deallocation.
-  // Allocates a block from the current chunk
+  // Allocate memory from Metaspace. Will attempt to allocate from the _block_freelists,
+  // failing that, from the current chunk; failing that, attempt to get a new chunk from
+  // the associated ChunkManager.
   MetaWord* allocate(size_t word_size);
 
-  // Helper for allocations
-  MetaWord* allocate_work(size_t word_size);
-
-  // Returns a block to the per manager freelist
+  // Prematurely returns a metaspace allocation to the _block_freelists because it is not
+  // needed anymore.
   void deallocate(MetaWord* p, size_t word_size);
 
-  // Based on the allocation size and a minimum chunk size,
-  // returned chunk size (for expanding space for chunk allocation).
-  size_t calc_chunk_size(size_t allocation_word_size);
-
-  // Called when an allocation from the current chunk fails.
-  // Gets a new chunk (may require getting a new virtual space),
-  // and allocates from that chunk.
-  MetaWord* grow_and_allocate(size_t word_size);
-
-  // Notify memory usage to MemoryService.
-  void track_metaspace_memory_usage();
-
-  // debugging support.
-
-  void print_on(outputStream* st) const;
-  void locked_print_chunks_in_use_on(outputStream* st) const;
-
-  void verify();
-  void verify_chunk_size(Metachunk* chunk);
-
-  // This adjusts the size given to be greater than the minimum allocation size in
-  // words for data in metaspace.  Esentially the minimum size is currently 3 words.
-  size_t get_allocation_word_size(size_t word_size) {
-    size_t byte_size = word_size * BytesPerWord;
-
-    size_t raw_bytes_size = MAX2(byte_size, sizeof(Metablock));
-    raw_bytes_size = align_up(raw_bytes_size, Metachunk::object_alignment());
-
-    size_t raw_word_size = raw_bytes_size / BytesPerWord;
-    assert(raw_word_size * BytesPerWord == raw_bytes_size, "Size problem");
-
-    return raw_word_size;
-  }
-
-  // Adds to the given statistic object.
+  // Update statistics. This walks all in-use chunks.
   void add_to_statistics(SpaceManagerStatistics* out) const;
 
-  // Verify internal counters against the current state.
-  DEBUG_ONLY(void verify_metrics() const;)
+  // Run verifications. slow=true: verify chunk-internal integrity too.
+  DEBUG_ONLY(void locked_verify(bool slow) const;)
 
 };
 
-
 } // namespace metaspace
 
 #endif // SHARE_MEMORY_METASPACE_SPACEMANAGER_HPP
< prev index next >