comparison src/share/vm/memory/metaspace.cpp @ 10330:2b1a9d972fc2

8014862: Add fast Metasapce capacity and used per MetadataType Reviewed-by: ehelin, stefank
author jmasa
date Mon, 20 May 2013 22:34:24 -0700
parents 601183f604b2
children a1ebd310d5c1
comparison
equal deleted inserted replaced
10329:10f759898d40 10330:2b1a9d972fc2
560 private: 560 private:
561 561
562 // protects allocations and contains. 562 // protects allocations and contains.
563 Mutex* const _lock; 563 Mutex* const _lock;
564 564
565 // Type of metadata allocated.
566 Metaspace::MetadataType _mdtype;
567
565 // Chunk related size 568 // Chunk related size
566 size_t _medium_chunk_bunch; 569 size_t _medium_chunk_bunch;
567 570
568 // List of chunks in use by this SpaceManager. Allocations 571 // List of chunks in use by this SpaceManager. Allocations
569 // are done from the current chunk. The list is used for deallocating 572 // are done from the current chunk. The list is used for deallocating
604 607
605 BlockFreelist* block_freelists() const { 608 BlockFreelist* block_freelists() const {
606 return (BlockFreelist*) &_block_freelists; 609 return (BlockFreelist*) &_block_freelists;
607 } 610 }
608 611
612 Metaspace::MetadataType mdtype() { return _mdtype; }
609 VirtualSpaceList* vs_list() const { return _vs_list; } 613 VirtualSpaceList* vs_list() const { return _vs_list; }
610 614
611 Metachunk* current_chunk() const { return _current_chunk; } 615 Metachunk* current_chunk() const { return _current_chunk; }
612 void set_current_chunk(Metachunk* v) { 616 void set_current_chunk(Metachunk* v) {
613 _current_chunk = v; 617 _current_chunk = v;
624 628
625 protected: 629 protected:
626 void initialize(); 630 void initialize();
627 631
628 public: 632 public:
629 SpaceManager(Mutex* lock, 633 SpaceManager(Metaspace::MetadataType mdtype,
634 Mutex* lock,
630 VirtualSpaceList* vs_list); 635 VirtualSpaceList* vs_list);
631 ~SpaceManager(); 636 ~SpaceManager();
632 637
633 enum ChunkMultiples { 638 enum ChunkMultiples {
634 MediumChunkMultiple = 4 639 MediumChunkMultiple = 4
2030 st->print_cr("total in block free lists " SIZE_FORMAT, 2035 st->print_cr("total in block free lists " SIZE_FORMAT,
2031 block_freelists()->total_size()); 2036 block_freelists()->total_size());
2032 } 2037 }
2033 } 2038 }
2034 2039
2035 SpaceManager::SpaceManager(Mutex* lock, 2040 SpaceManager::SpaceManager(Metaspace::MetadataType mdtype,
2041 Mutex* lock,
2036 VirtualSpaceList* vs_list) : 2042 VirtualSpaceList* vs_list) :
2037 _vs_list(vs_list), 2043 _vs_list(vs_list),
2044 _mdtype(mdtype),
2038 _allocated_blocks_words(0), 2045 _allocated_blocks_words(0),
2039 _allocated_chunks_words(0), 2046 _allocated_chunks_words(0),
2040 _allocated_chunks_count(0), 2047 _allocated_chunks_count(0),
2041 _lock(lock) 2048 _lock(lock)
2042 { 2049 {
2048 // Total of allocated Metachunks and allocated Metachunks count 2055 // Total of allocated Metachunks and allocated Metachunks count
2049 // for each SpaceManager 2056 // for each SpaceManager
2050 _allocated_chunks_words = _allocated_chunks_words + words; 2057 _allocated_chunks_words = _allocated_chunks_words + words;
2051 _allocated_chunks_count++; 2058 _allocated_chunks_count++;
2052 // Global total of capacity in allocated Metachunks 2059 // Global total of capacity in allocated Metachunks
2053 MetaspaceAux::inc_capacity(words); 2060 MetaspaceAux::inc_capacity(mdtype(), words);
2054 // Global total of allocated Metablocks. 2061 // Global total of allocated Metablocks.
2055 // used_words_slow() includes the overhead in each 2062 // used_words_slow() includes the overhead in each
2056 // Metachunk so include it in the used when the 2063 // Metachunk so include it in the used when the
2057 // Metachunk is first added (so only added once per 2064 // Metachunk is first added (so only added once per
2058 // Metachunk). 2065 // Metachunk).
2059 MetaspaceAux::inc_used(Metachunk::overhead()); 2066 MetaspaceAux::inc_used(mdtype(), Metachunk::overhead());
2060 } 2067 }
2061 2068
2062 void SpaceManager::inc_used_metrics(size_t words) { 2069 void SpaceManager::inc_used_metrics(size_t words) {
2063 // Add to the per SpaceManager total 2070 // Add to the per SpaceManager total
2064 Atomic::add_ptr(words, &_allocated_blocks_words); 2071 Atomic::add_ptr(words, &_allocated_blocks_words);
2065 // Add to the global total 2072 // Add to the global total
2066 MetaspaceAux::inc_used(words); 2073 MetaspaceAux::inc_used(mdtype(), words);
2067 } 2074 }
2068 2075
2069 void SpaceManager::dec_total_from_size_metrics() { 2076 void SpaceManager::dec_total_from_size_metrics() {
2070 MetaspaceAux::dec_capacity(allocated_chunks_words()); 2077 MetaspaceAux::dec_capacity(mdtype(), allocated_chunks_words());
2071 MetaspaceAux::dec_used(allocated_blocks_words()); 2078 MetaspaceAux::dec_used(mdtype(), allocated_blocks_words());
2072 // Also deduct the overhead per Metachunk 2079 // Also deduct the overhead per Metachunk
2073 MetaspaceAux::dec_used(allocated_chunks_count() * Metachunk::overhead()); 2080 MetaspaceAux::dec_used(mdtype(), allocated_chunks_count() * Metachunk::overhead());
2074 } 2081 }
2075 2082
2076 void SpaceManager::initialize() { 2083 void SpaceManager::initialize() {
2077 Metadebug::init_allocation_fail_alot_count(); 2084 Metadebug::init_allocation_fail_alot_count();
2078 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { 2085 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
2468 #endif // PRODUCT 2475 #endif // PRODUCT
2469 2476
2470 // MetaspaceAux 2477 // MetaspaceAux
2471 2478
2472 2479
2473 size_t MetaspaceAux::_allocated_capacity_words = 0; 2480 size_t MetaspaceAux::_allocated_capacity_words[] = {0, 0};
2474 size_t MetaspaceAux::_allocated_used_words = 0; 2481 size_t MetaspaceAux::_allocated_used_words[] = {0, 0};
2475 2482
2476 size_t MetaspaceAux::free_bytes() { 2483 size_t MetaspaceAux::free_bytes() {
2477 size_t result = 0; 2484 size_t result = 0;
2478 if (Metaspace::class_space_list() != NULL) { 2485 if (Metaspace::class_space_list() != NULL) {
2479 result = result + Metaspace::class_space_list()->free_bytes(); 2486 result = result + Metaspace::class_space_list()->free_bytes();
2482 result = result + Metaspace::space_list()->free_bytes(); 2489 result = result + Metaspace::space_list()->free_bytes();
2483 } 2490 }
2484 return result; 2491 return result;
2485 } 2492 }
2486 2493
2487 void MetaspaceAux::dec_capacity(size_t words) { 2494 void MetaspaceAux::dec_capacity(Metaspace::MetadataType mdtype, size_t words) {
2488 assert_lock_strong(SpaceManager::expand_lock()); 2495 assert_lock_strong(SpaceManager::expand_lock());
2489 assert(words <= _allocated_capacity_words, 2496 assert(words <= allocated_capacity_words(mdtype),
2490 err_msg("About to decrement below 0: words " SIZE_FORMAT 2497 err_msg("About to decrement below 0: words " SIZE_FORMAT
2491 " is greater than _allocated_capacity_words " SIZE_FORMAT, 2498 " is greater than _allocated_capacity_words[%u] " SIZE_FORMAT,
2492 words, _allocated_capacity_words)); 2499 words, mdtype, allocated_capacity_words(mdtype)));
2493 _allocated_capacity_words = _allocated_capacity_words - words; 2500 _allocated_capacity_words[mdtype] -= words;
2494 } 2501 }
2495 2502
2496 void MetaspaceAux::inc_capacity(size_t words) { 2503 void MetaspaceAux::inc_capacity(Metaspace::MetadataType mdtype, size_t words) {
2497 assert_lock_strong(SpaceManager::expand_lock()); 2504 assert_lock_strong(SpaceManager::expand_lock());
2498 // Needs to be atomic 2505 // Needs to be atomic
2499 _allocated_capacity_words = _allocated_capacity_words + words; 2506 _allocated_capacity_words[mdtype] += words;
2500 } 2507 }
2501 2508
2502 void MetaspaceAux::dec_used(size_t words) { 2509 void MetaspaceAux::dec_used(Metaspace::MetadataType mdtype, size_t words) {
2503 assert(words <= _allocated_used_words, 2510 assert(words <= allocated_used_words(mdtype),
2504 err_msg("About to decrement below 0: words " SIZE_FORMAT 2511 err_msg("About to decrement below 0: words " SIZE_FORMAT
2505 " is greater than _allocated_used_words " SIZE_FORMAT, 2512 " is greater than _allocated_used_words[%u] " SIZE_FORMAT,
2506 words, _allocated_used_words)); 2513 words, mdtype, allocated_used_words(mdtype)));
2507 // For CMS deallocation of the Metaspaces occurs during the 2514 // For CMS deallocation of the Metaspaces occurs during the
2508 // sweep which is a concurrent phase. Protection by the expand_lock() 2515 // sweep which is a concurrent phase. Protection by the expand_lock()
2509 // is not enough since allocation is on a per Metaspace basis 2516 // is not enough since allocation is on a per Metaspace basis
2510 // and protected by the Metaspace lock. 2517 // and protected by the Metaspace lock.
2511 jlong minus_words = (jlong) - (jlong) words; 2518 jlong minus_words = (jlong) - (jlong) words;
2512 Atomic::add_ptr(minus_words, &_allocated_used_words); 2519 Atomic::add_ptr(minus_words, &_allocated_used_words[mdtype]);
2513 } 2520 }
2514 2521
2515 void MetaspaceAux::inc_used(size_t words) { 2522 void MetaspaceAux::inc_used(Metaspace::MetadataType mdtype, size_t words) {
2516 // _allocated_used_words tracks allocations for 2523 // _allocated_used_words tracks allocations for
2517 // each piece of metadata. Those allocations are 2524 // each piece of metadata. Those allocations are
2518 // generally done concurrently by different application 2525 // generally done concurrently by different application
2519 // threads so must be done atomically. 2526 // threads so must be done atomically.
2520 Atomic::add_ptr(words, &_allocated_used_words); 2527 Atomic::add_ptr(words, &_allocated_used_words[mdtype]);
2521 } 2528 }
2522 2529
2523 size_t MetaspaceAux::used_bytes_slow(Metaspace::MetadataType mdtype) { 2530 size_t MetaspaceAux::used_bytes_slow(Metaspace::MetadataType mdtype) {
2524 size_t used = 0; 2531 size_t used = 0;
2525 ClassLoaderDataGraphMetaspaceIterator iter; 2532 ClassLoaderDataGraphMetaspaceIterator iter;
2617 2624
2618 out->print_cr(" Metaspace total " 2625 out->print_cr(" Metaspace total "
2619 SIZE_FORMAT "K, used " SIZE_FORMAT "K," 2626 SIZE_FORMAT "K, used " SIZE_FORMAT "K,"
2620 " reserved " SIZE_FORMAT "K", 2627 " reserved " SIZE_FORMAT "K",
2621 allocated_capacity_bytes()/K, allocated_used_bytes()/K, reserved_in_bytes()/K); 2628 allocated_capacity_bytes()/K, allocated_used_bytes()/K, reserved_in_bytes()/K);
2622 #if 0 2629
2623 // The calls to capacity_bytes_slow() and used_bytes_slow() cause 2630 out->print_cr(" data space "
2624 // lock ordering assertion failures with some collectors. Do 2631 SIZE_FORMAT "K, used " SIZE_FORMAT "K,"
2625 // not include this code until the lock ordering is fixed. 2632 " reserved " SIZE_FORMAT "K",
2626 if (PrintGCDetails && Verbose) { 2633 allocated_capacity_bytes(nct)/K,
2627 out->print_cr(" data space " 2634 allocated_used_bytes(nct)/K,
2628 SIZE_FORMAT "K, used " SIZE_FORMAT "K," 2635 reserved_in_bytes(nct)/K);
2629 " reserved " SIZE_FORMAT "K", 2636 out->print_cr(" class space "
2630 capacity_bytes_slow(nct)/K, used_bytes_slow(nct)/K, reserved_in_bytes(nct)/K); 2637 SIZE_FORMAT "K, used " SIZE_FORMAT "K,"
2631 out->print_cr(" class space " 2638 " reserved " SIZE_FORMAT "K",
2632 SIZE_FORMAT "K, used " SIZE_FORMAT "K," 2639 allocated_capacity_bytes(ct)/K,
2633 " reserved " SIZE_FORMAT "K", 2640 allocated_used_bytes(ct)/K,
2634 capacity_bytes_slow(ct)/K, used_bytes_slow(ct)/K, reserved_in_bytes(ct)/K); 2641 reserved_in_bytes(ct)/K);
2635 }
2636 #endif
2637 } 2642 }
2638 2643
2639 // Print information for class space and data space separately. 2644 // Print information for class space and data space separately.
2640 // This is almost the same as above. 2645 // This is almost the same as above.
2641 void MetaspaceAux::print_on(outputStream* out, Metaspace::MetadataType mdtype) { 2646 void MetaspaceAux::print_on(outputStream* out, Metaspace::MetadataType mdtype) {
2715 } 2720 }
2716 2721
2717 void MetaspaceAux::verify_capacity() { 2722 void MetaspaceAux::verify_capacity() {
2718 #ifdef ASSERT 2723 #ifdef ASSERT
2719 size_t running_sum_capacity_bytes = allocated_capacity_bytes(); 2724 size_t running_sum_capacity_bytes = allocated_capacity_bytes();
2720 // For purposes of the running sum of used, verify against capacity 2725 // For purposes of the running sum of capacity, verify against capacity
2721 size_t capacity_in_use_bytes = capacity_bytes_slow(); 2726 size_t capacity_in_use_bytes = capacity_bytes_slow();
2722 assert(running_sum_capacity_bytes == capacity_in_use_bytes, 2727 assert(running_sum_capacity_bytes == capacity_in_use_bytes,
2723 err_msg("allocated_capacity_words() * BytesPerWord " SIZE_FORMAT 2728 err_msg("allocated_capacity_words() * BytesPerWord " SIZE_FORMAT
2724 " capacity_bytes_slow()" SIZE_FORMAT, 2729 " capacity_bytes_slow()" SIZE_FORMAT,
2725 running_sum_capacity_bytes, capacity_in_use_bytes)); 2730 running_sum_capacity_bytes, capacity_in_use_bytes));
2731 for (Metaspace::MetadataType i = Metaspace::ClassType;
2732 i < Metaspace:: MetadataTypeCount;
2733 i = (Metaspace::MetadataType)(i + 1)) {
2734 size_t capacity_in_use_bytes = capacity_bytes_slow(i);
2735 assert(allocated_capacity_bytes(i) == capacity_in_use_bytes,
2736 err_msg("allocated_capacity_bytes(%u) " SIZE_FORMAT
2737 " capacity_bytes_slow(%u)" SIZE_FORMAT,
2738 i, allocated_capacity_bytes(i), i, capacity_in_use_bytes));
2739 }
2726 #endif 2740 #endif
2727 } 2741 }
2728 2742
2729 void MetaspaceAux::verify_used() { 2743 void MetaspaceAux::verify_used() {
2730 #ifdef ASSERT 2744 #ifdef ASSERT
2731 size_t running_sum_used_bytes = allocated_used_bytes(); 2745 size_t running_sum_used_bytes = allocated_used_bytes();
2732 // For purposes of the running sum of used, verify against capacity 2746 // For purposes of the running sum of used, verify against used
2733 size_t used_in_use_bytes = used_bytes_slow(); 2747 size_t used_in_use_bytes = used_bytes_slow();
2734 assert(allocated_used_bytes() == used_in_use_bytes, 2748 assert(allocated_used_bytes() == used_in_use_bytes,
2735 err_msg("allocated_used_bytes() " SIZE_FORMAT 2749 err_msg("allocated_used_bytes() " SIZE_FORMAT
2736 " used_bytes_slow()()" SIZE_FORMAT, 2750 " used_bytes_slow()" SIZE_FORMAT,
2737 allocated_used_bytes(), used_in_use_bytes)); 2751 allocated_used_bytes(), used_in_use_bytes));
2752 for (Metaspace::MetadataType i = Metaspace::ClassType;
2753 i < Metaspace:: MetadataTypeCount;
2754 i = (Metaspace::MetadataType)(i + 1)) {
2755 size_t used_in_use_bytes = used_bytes_slow(i);
2756 assert(allocated_used_bytes(i) == used_in_use_bytes,
2757 err_msg("allocated_used_bytes(%u) " SIZE_FORMAT
2758 " used_bytes_slow(%u)" SIZE_FORMAT,
2759 i, allocated_used_bytes(i), i, used_in_use_bytes));
2760 }
2738 #endif 2761 #endif
2739 } 2762 }
2740 2763
2741 void MetaspaceAux::verify_metrics() { 2764 void MetaspaceAux::verify_metrics() {
2742 verify_capacity(); 2765 verify_capacity();
2833 MetaspaceType type) { 2856 MetaspaceType type) {
2834 2857
2835 assert(space_list() != NULL, 2858 assert(space_list() != NULL,
2836 "Metadata VirtualSpaceList has not been initialized"); 2859 "Metadata VirtualSpaceList has not been initialized");
2837 2860
2838 _vsm = new SpaceManager(lock, space_list()); 2861 _vsm = new SpaceManager(Metaspace::NonClassType, lock, space_list());
2839 if (_vsm == NULL) { 2862 if (_vsm == NULL) {
2840 return; 2863 return;
2841 } 2864 }
2842 size_t word_size; 2865 size_t word_size;
2843 size_t class_word_size; 2866 size_t class_word_size;
2847 2870
2848 assert(class_space_list() != NULL, 2871 assert(class_space_list() != NULL,
2849 "Class VirtualSpaceList has not been initialized"); 2872 "Class VirtualSpaceList has not been initialized");
2850 2873
2851 // Allocate SpaceManager for classes. 2874 // Allocate SpaceManager for classes.
2852 _class_vsm = new SpaceManager(lock, class_space_list()); 2875 _class_vsm = new SpaceManager(Metaspace::ClassType, lock, class_space_list());
2853 if (_class_vsm == NULL) { 2876 if (_class_vsm == NULL) {
2854 return; 2877 return;
2855 } 2878 }
2856 2879
2857 MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); 2880 MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag);