< prev index next >

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

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

*** 26,233 **** #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/metachunk.hpp" ! #include "memory/metaspace/metaspaceStatistics.hpp" ! #include "utilities/debug.hpp" ! #include "utilities/globalDefinitions.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; ! private: ! // protects allocations Mutex* const _lock; ! // Type of metadata allocated. ! const Metaspace::MetadataType _mdtype; ! // Type of metaspace ! const Metaspace::MetaspaceType _space_type; // 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; Metachunk* _current_chunk; ! enum { ! ! // Maximum number of small chunks to allocate to a SpaceManager ! small_chunk_limit = 4, - // 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 ! }; ! ! // Some running counters, but lets keep their number small to not add to much to ! // the per-classloader footprint. // 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; } - 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; ! } ! Metachunk* find_current_chunk(size_t word_size); ! // Add chunk to the list of chunks in use ! void add_chunk(Metachunk* v, bool make_current); void retire_current_chunk(); ! Mutex* lock() const { return _lock; } ! // Adds to the given statistic object. Expects to be locked with lock(). ! void add_to_statistics_locked(SpaceManagerStatistics* out) const; ! // Verify internal counters against the current state. Expects to be locked with lock(). ! DEBUG_ONLY(void verify_metrics_locked() const;) - 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 MetaWord* allocate(size_t word_size); ! // Helper for allocations ! MetaWord* allocate_work(size_t word_size); ! ! // Returns a block to the per manager freelist 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. void add_to_statistics(SpaceManagerStatistics* out) const; ! // Verify internal counters against the current state. ! DEBUG_ONLY(void verify_metrics() const;) }; - } // namespace metaspace #endif // SHARE_MEMORY_METASPACE_SPACEMANAGER_HPP --- 26,125 ---- #define SHARE_MEMORY_METASPACE_SPACEMANAGER_HPP #include "memory/allocation.hpp" #include "memory/metaspace.hpp" #include "memory/metaspace/blockFreelist.hpp" ! #include "memory/metaspace/chunkAllocSequence.hpp" ! #include "memory/metaspace/chunkManager.hpp" #include "memory/metaspace/metachunk.hpp" ! #include "memory/metaspace/metaspaceCommon.hpp" class outputStream; class Mutex; namespace metaspace { ! class SpaceManagerStatistics; ! // 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) ! class SpaceManager : public CHeapObj<mtClass> { ! ! // Lock handed down from the associated ClassLoaderData. ! // Protects allocations from this space. Mutex* const _lock; ! // The chunk manager to allocate chunks from. ! ChunkManager* const _chunk_manager; ! // 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. ! MetachunkList _chunks; Metachunk* _current_chunk; ! // Prematurely released metablocks. ! BlockFreelist* _block_freelist; ! // Statistics ! // 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_level[chklvl::NUM_CHUNK_LEVELS]; ! uintx _num_chunks_total; ! Mutex* lock() const { return _lock; } ! ChunkManager* chunk_manager() const { return _chunk_manager; } ! const ChunkAllocSequence* chunk_alloc_sequence() const { return _chunk_alloc_sequence; } ! BlockFreelist* block_freelist() const { return _block_freelist; } ! void create_block_freelist(); ! // 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(); ! // 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); ! public: ! SpaceManager(ChunkManager* chunk_manager, const ChunkAllocSequence* alloc_sequence, Mutex* lock); ~SpaceManager(); ! // 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); ! // Prematurely returns a metaspace allocation to the _block_freelists because it is not ! // needed anymore. void deallocate(MetaWord* p, size_t word_size); ! // Update statistics. This walks all in-use chunks. void add_to_statistics(SpaceManagerStatistics* out) 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 >