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