Mercurial > hg > truffle
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); |