2727 out->print_cr(" Committed size : " SIZE_FORMAT_W(7) " KB", CodeCache::capacity() / K); 2728 out->print_cr(" Unallocated capacity : " SIZE_FORMAT_W(7) " KB", CodeCache::unallocated_capacity() / K); 2729 out->cr(); 2730 2731 out->cr(); 2732 out->print_cr("CodeCache cleaning overview"); 2733 out->print_cr("--------------------------------------------------------"); 2734 out->cr(); 2735 NMethodSweeper::print(out); 2736 out->print_cr("--------------------------------------------------------"); 2737 out->cr(); 2738 } 2739 2740 // Note: tty_lock must not be held upon entry to this function. 2741 // Print functions called from herein do "micro-locking" on tty_lock. 2742 // That's a tradeoff which keeps together important blocks of output. 2743 // At the same time, continuous tty_lock hold time is kept in check, 2744 // preventing concurrently printing threads from stalling a long time. 2745 void CompileBroker::print_heapinfo(outputStream* out, const char* function, size_t granularity) { 2746 TimeStamp ts_total; 2747 TimeStamp ts; 2748 2749 bool allFun = !strcmp(function, "all"); 2750 bool aggregate = !strcmp(function, "aggregate") || !strcmp(function, "analyze") || allFun; 2751 bool usedSpace = !strcmp(function, "UsedSpace") || allFun; 2752 bool freeSpace = !strcmp(function, "FreeSpace") || allFun; 2753 bool methodCount = !strcmp(function, "MethodCount") || allFun; 2754 bool methodSpace = !strcmp(function, "MethodSpace") || allFun; 2755 bool methodAge = !strcmp(function, "MethodAge") || allFun; 2756 bool methodNames = !strcmp(function, "MethodNames") || allFun; 2757 bool discard = !strcmp(function, "discard") || allFun; 2758 2759 if (out == NULL) { 2760 out = tty; 2761 } 2762 2763 if (!(aggregate || usedSpace || freeSpace || methodCount || methodSpace || methodAge || methodNames || discard)) { 2764 out->print_cr("\n__ CodeHeapStateAnalytics: Function %s is not supported", function); 2765 out->cr(); 2766 return; 2767 } 2768 2769 ts_total.update(); // record starting point 2770 2771 if (aggregate) { 2772 print_info(out); 2773 } 2774 2775 // We hold the CodeHeapStateAnalytics_lock all the time, from here until we leave this function. 2776 // That helps us getting a consistent view on the CodeHeap, at least for the "all" function. 2777 // When we request individual parts of the analysis via the jcmd interface, it is possible 2778 // that in between another thread (another jcmd user or the vm running into CodeCache OOM) 2779 // updated the aggregated data. That's a tolerable tradeoff because we can't hold a lock 2780 // across user interaction. 2781 ts.update(); // record starting point 2782 MutexLockerEx mu1(CodeHeapStateAnalytics_lock, Mutex::_no_safepoint_check_flag); 2783 out->cr(); 2784 out->print_cr("__ CodeHeapStateAnalytics lock wait took %10.3f seconds _________", ts.seconds()); 2785 out->cr(); 2786 2787 if (aggregate) { 2788 // It is sufficient to hold the CodeCache_lock only for the aggregate step. 2789 // All other functions operate on aggregated data - except MethodNames, but that should be safe. 2790 // The separate CodeHeapStateAnalytics_lock protects the printing functions against 2791 // concurrent aggregate steps. Acquire this lock before acquiring the CodeCache_lock. 2792 // CodeHeapStateAnalytics_lock could be held by a concurrent thread for a long time, 2793 // leading to an unnecessarily long hold time of the CodeCache_lock. 2794 ts.update(); // record starting point 2795 MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag); 2796 out->cr(); 2797 out->print_cr("__ CodeCache lock wait took %10.3f seconds _________", ts.seconds()); 2798 out->cr(); 2799 2800 ts.update(); // record starting point 2801 CodeCache::aggregate(out, granularity); 2802 out->cr(); 2803 out->print_cr("__ CodeCache lock hold took %10.3f seconds _________", ts.seconds()); 2804 out->cr(); 2805 } 2806 2807 if (usedSpace) CodeCache::print_usedSpace(out); 2808 if (freeSpace) CodeCache::print_freeSpace(out); 2809 if (methodCount) CodeCache::print_count(out); 2810 if (methodSpace) CodeCache::print_space(out); 2811 if (methodAge) CodeCache::print_age(out); 2812 if (methodNames) CodeCache::print_names(out); 2813 if (discard) CodeCache::discard(out); 2814 2815 out->cr(); 2816 out->print_cr("__ CodeHeapStateAnalytics total duration %10.3f seconds _________", ts_total.seconds()); 2817 out->cr(); 2818 } | 2727 out->print_cr(" Committed size : " SIZE_FORMAT_W(7) " KB", CodeCache::capacity() / K); 2728 out->print_cr(" Unallocated capacity : " SIZE_FORMAT_W(7) " KB", CodeCache::unallocated_capacity() / K); 2729 out->cr(); 2730 2731 out->cr(); 2732 out->print_cr("CodeCache cleaning overview"); 2733 out->print_cr("--------------------------------------------------------"); 2734 out->cr(); 2735 NMethodSweeper::print(out); 2736 out->print_cr("--------------------------------------------------------"); 2737 out->cr(); 2738 } 2739 2740 // Note: tty_lock must not be held upon entry to this function. 2741 // Print functions called from herein do "micro-locking" on tty_lock. 2742 // That's a tradeoff which keeps together important blocks of output. 2743 // At the same time, continuous tty_lock hold time is kept in check, 2744 // preventing concurrently printing threads from stalling a long time. 2745 void CompileBroker::print_heapinfo(outputStream* out, const char* function, size_t granularity) { 2746 TimeStamp ts_total; 2747 TimeStamp ts_global; 2748 TimeStamp ts; 2749 2750 bool allFun = !strcmp(function, "all"); 2751 bool aggregate = !strcmp(function, "aggregate") || !strcmp(function, "analyze") || allFun; 2752 bool usedSpace = !strcmp(function, "UsedSpace") || allFun; 2753 bool freeSpace = !strcmp(function, "FreeSpace") || allFun; 2754 bool methodCount = !strcmp(function, "MethodCount") || allFun; 2755 bool methodSpace = !strcmp(function, "MethodSpace") || allFun; 2756 bool methodAge = !strcmp(function, "MethodAge") || allFun; 2757 bool methodNames = !strcmp(function, "MethodNames") || allFun; 2758 bool discard = !strcmp(function, "discard") || allFun; 2759 2760 if (out == NULL) { 2761 out = tty; 2762 } 2763 2764 if (!(aggregate || usedSpace || freeSpace || methodCount || methodSpace || methodAge || methodNames || discard)) { 2765 out->print_cr("\n__ CodeHeapStateAnalytics: Function %s is not supported", function); 2766 out->cr(); 2767 return; 2768 } 2769 2770 ts_total.update(); // record starting point 2771 2772 if (aggregate) { 2773 print_info(out); 2774 } 2775 2776 // We hold the CodeHeapStateAnalytics_lock all the time, from here until we leave this function. 2777 // That prevents other threads from destroying (making inconsistent) our view on the CodeHeap. 2778 // When we request individual parts of the analysis via the jcmd interface, it is possible 2779 // that in between another thread (another jcmd user or the vm running into CodeCache OOM) 2780 // updated the aggregated data. We will then see a modified, but again consistent, view 2781 // on the CodeHeap. That's a tolerable tradeoff we have to accept because we can't hold 2782 // a lock across user interaction. 2783 2784 // We should definitely acquire this lock before acquiring Compile_lock and CodeCache_lock. 2785 // CodeHeapStateAnalytics_lock may be held by a concurrent thread for a long time, 2786 // leading to an unnecessarily long hold time of the other locks we acquired before. 2787 ts.update(); // record starting point 2788 MutexLockerEx mu0(CodeHeapStateAnalytics_lock); 2789 out->print_cr("\n__ CodeHeapStateAnalytics lock wait took %10.3f seconds _________\n", ts.seconds()); 2790 2791 // Holding the CodeCache_lock protects from concurrent alterations of the CodeCache. 2792 // Unfortunately, such protection is not sufficient: 2793 // When a new nmethod is created via ciEnv::register_method(), the 2794 // Compile_lock is taken first. After some initializations, 2795 // nmethod::new_nmethod() takes over, grabbing the CodeCache_lock 2796 // immediately (after finalizing the oop references). To lock out concurrent 2797 // modifiers, we have to grab both locks as well in the described sequence. 2798 // 2799 // If we serve an "allFun" call, it is beneficial to hold CodeCache_lock and Compile_lock 2800 // for the entire duration of aggregation and printing. That makes sure we see 2801 // a consistent picture and do not run into issues caused by concurrent alterations. 2802 bool should_take_Compile_lock = !SafepointSynchronize::is_at_safepoint() && 2803 !Compile_lock->owned_by_self(); 2804 bool should_take_CodeCache_lock = !SafepointSynchronize::is_at_safepoint() && 2805 !CodeCache_lock->owned_by_self(); 2806 Mutex* global_lock_1 = allFun ? (should_take_Compile_lock ? Compile_lock : NULL) : NULL; 2807 Monitor* global_lock_2 = allFun ? (should_take_CodeCache_lock ? CodeCache_lock : NULL) : NULL; 2808 Mutex* function_lock_1 = allFun ? NULL : (should_take_Compile_lock ? Compile_lock : NULL); 2809 Monitor* function_lock_2 = allFun ? NULL : (should_take_CodeCache_lock ? CodeCache_lock : NULL); 2810 ts_global.update(); // record starting point 2811 MutexLockerEx mu1(global_lock_1, Mutex::_no_safepoint_check_flag); 2812 MutexLockerEx mu2(global_lock_2, Mutex::_no_safepoint_check_flag); 2813 if ((global_lock_1 != NULL) || (global_lock_2 != NULL)) { 2814 out->print_cr("\n__ Compile & CodeCache (global) lock wait took %10.3f seconds _________\n", ts_global.seconds()); 2815 ts_global.update(); // record starting point 2816 } 2817 2818 if (aggregate) { 2819 ts.update(); // record starting point 2820 MutexLockerEx mu11(function_lock_1, Mutex::_no_safepoint_check_flag); 2821 MutexLockerEx mu22(function_lock_2, Mutex::_no_safepoint_check_flag); 2822 if ((function_lock_1 != NULL) || (function_lock_2 != NULL)) { 2823 out->print_cr("\n__ Compile & CodeCache (function) lock wait took %10.3f seconds _________\n", ts.seconds()); 2824 } 2825 2826 ts.update(); // record starting point 2827 CodeCache::aggregate(out, granularity); 2828 if ((function_lock_1 != NULL) || (function_lock_2 != NULL)) { 2829 out->print_cr("\n__ Compile & CodeCache (function) lock hold took %10.3f seconds _________\n", ts.seconds()); 2830 } 2831 } 2832 2833 if (usedSpace) CodeCache::print_usedSpace(out); 2834 if (freeSpace) CodeCache::print_freeSpace(out); 2835 if (methodCount) CodeCache::print_count(out); 2836 if (methodSpace) CodeCache::print_space(out); 2837 if (methodAge) CodeCache::print_age(out); 2838 if (methodNames) { 2839 if (allFun) { 2840 // print_names() can only be used safely if the locks have been continuously held 2841 // since aggregation begin. That is true only for function "all". 2842 CodeCache::print_names(out); 2843 } else { 2844 out->print_cr("\nCodeHeapStateAnalytics: Function 'MethodNames' is only available as part of function 'all'"); 2845 } 2846 } 2847 if (discard) CodeCache::discard(out); 2848 2849 if ((global_lock_1 != NULL) || (global_lock_2 != NULL)) { 2850 out->print_cr("\n__ Compile & CodeCache (global) lock hold took %10.3f seconds _________\n", ts_global.seconds()); 2851 } 2852 out->print_cr("\n__ CodeHeapStateAnalytics total duration %10.3f seconds _________\n", ts_total.seconds()); 2853 } |