1 /* 2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "classfile/systemDictionary.hpp" 27 #include "gc_interface/collectedHeap.inline.hpp" 28 #include "memory/permGen.hpp" 29 #include "memory/resourceArea.hpp" 30 #include "memory/space.hpp" 31 #include "oops/oop.inline.hpp" 32 #include "oops/oop.inline2.hpp" 33 #include "runtime/aprofiler.hpp" 34 35 36 bool AllocationProfiler::_active = false; 37 GrowableArray<klassOop>* AllocationProfiler::_print_array = NULL; 38 39 40 class AllocProfClosure : public ObjectClosure { 41 public: 42 void do_object(oop obj) { 43 Klass* k = obj->blueprint(); 44 k->set_alloc_count(k->alloc_count() + 1); 45 k->set_alloc_size(k->alloc_size() + obj->size()); 46 } 47 }; 48 49 50 #ifndef PRODUCT 51 52 class AllocProfResetClosure : public ObjectClosure { 53 public: 54 void do_object(oop obj) { 55 if (obj->is_klass()) { 56 Klass* k = Klass::cast(klassOop(obj)); 57 k->set_alloc_count(0); 58 k->set_alloc_size(0); 59 } 60 } 61 }; 62 63 #endif 64 65 66 void AllocationProfiler::iterate_since_last_gc() { 67 if (is_active()) { 68 AllocProfClosure blk; 69 GenCollectedHeap* heap = GenCollectedHeap::heap(); 70 heap->object_iterate_since_last_GC(&blk); 71 } 72 } 73 74 75 void AllocationProfiler::engage() { 76 _active = true; 77 } 78 79 80 void AllocationProfiler::disengage() { 81 _active = false; 82 } 83 84 85 void AllocationProfiler::add_class_to_array(klassOop k) { 86 _print_array->append(k); 87 } 88 89 90 void AllocationProfiler::add_classes_to_array(klassOop k) { 91 // Iterate over klass and all array klasses for klass 92 k->klass_part()->with_array_klasses_do(&AllocationProfiler::add_class_to_array); 93 } 94 95 96 int AllocationProfiler::compare_classes(klassOop* k1, klassOop* k2) { 97 // Sort by total allocation size 98 return (*k2)->klass_part()->alloc_size() - (*k1)->klass_part()->alloc_size(); 99 } 100 101 102 int AllocationProfiler::average(size_t alloc_size, int alloc_count) { 103 return (int) ((double) (alloc_size * BytesPerWord) / MAX2(alloc_count, 1) + 0.5); 104 } 105 106 107 void AllocationProfiler::sort_and_print_array(size_t cutoff) { 108 _print_array->sort(&AllocationProfiler::compare_classes); 109 tty->print_cr("________________Size" 110 "__Instances" 111 "__Average" 112 "__Class________________"); 113 size_t total_alloc_size = 0; 114 int total_alloc_count = 0; 115 for (int index = 0; index < _print_array->length(); index++) { 116 klassOop k = _print_array->at(index); 117 size_t alloc_size = k->klass_part()->alloc_size(); 118 if (alloc_size > cutoff) { 119 int alloc_count = k->klass_part()->alloc_count(); 120 #ifdef PRODUCT 121 const char* name = k->klass_part()->external_name(); 122 #else 123 const char* name = k->klass_part()->internal_name(); 124 #endif 125 tty->print_cr("%20u %10u %8u %s", 126 alloc_size * BytesPerWord, 127 alloc_count, 128 average(alloc_size, alloc_count), 129 name); 130 total_alloc_size += alloc_size; 131 total_alloc_count += alloc_count; 132 } 133 } 134 tty->print_cr("%20u %10u %8u --total--", 135 total_alloc_size * BytesPerWord, 136 total_alloc_count, 137 average(total_alloc_size, total_alloc_count)); 138 tty->cr(); 139 } 140 141 142 void AllocationProfiler::print(size_t cutoff) { 143 ResourceMark rm; 144 assert(!is_active(), "AllocationProfiler cannot be active while printing profile"); 145 146 tty->cr(); 147 tty->print_cr("Allocation profile (sizes in bytes, cutoff = %ld bytes):", cutoff * BytesPerWord); 148 tty->cr(); 149 150 // Print regular instance klasses and basic type array klasses 151 _print_array = new GrowableArray<klassOop>(SystemDictionary::number_of_classes()*2); 152 SystemDictionary::classes_do(&add_classes_to_array); 153 Universe::basic_type_classes_do(&add_classes_to_array); 154 sort_and_print_array(cutoff); 155 156 #ifndef PRODUCT 157 tty->print_cr("Allocation profile for system classes (sizes in bytes, cutoff = %d bytes):", cutoff * BytesPerWord); 158 tty->cr(); 159 160 // Print system klasses (methods, symbols, constant pools, etc.) 161 _print_array = new GrowableArray<klassOop>(64); 162 Universe::system_classes_do(&add_classes_to_array); 163 sort_and_print_array(cutoff); 164 165 tty->print_cr("Permanent generation dump (sizes in bytes, cutoff = %d bytes):", cutoff * BytesPerWord); 166 tty->cr(); 167 168 AllocProfResetClosure resetblk; 169 Universe::heap()->permanent_object_iterate(&resetblk); 170 AllocProfClosure blk; 171 Universe::heap()->permanent_object_iterate(&blk); 172 173 _print_array = new GrowableArray<klassOop>(SystemDictionary::number_of_classes()*2); 174 SystemDictionary::classes_do(&add_classes_to_array); 175 Universe::basic_type_classes_do(&add_classes_to_array); 176 Universe::system_classes_do(&add_classes_to_array); 177 sort_and_print_array(cutoff); 178 #endif 179 }