174 // Switch to the new storage 175 _buckets = buckets_new; 176 177 return true; 178 } 179 180 template <MEMFLAGS F> bool BasicHashtable<F>::maybe_grow(int max_size, int load_factor) { 181 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); 182 183 if (table_size() >= max_size) { 184 return false; 185 } 186 if (number_of_entries() / table_size() > load_factor) { 187 resize(MIN2<int>(table_size() * 2, max_size)); 188 return true; 189 } else { 190 return false; 191 } 192 } 193 194 // Dump footprint and bucket length statistics 195 // 196 // Note: if you create a new subclass of Hashtable<MyNewType, F>, you will need to 197 // add a new function static int literal_size(MyNewType lit) 198 // because I can't get template <class T> int literal_size(T) to pick the specializations for Symbol and oop. 199 // 200 // The StringTable and SymbolTable dumping print how much footprint is used by the String and Symbol 201 // literals. 202 203 template <class T, MEMFLAGS F> void Hashtable<T, F>::print_table_statistics(outputStream* st, 204 const char *table_name, 205 T (*literal_load_barrier)(HashtableEntry<T, F>*)) { 206 NumberSeq summary; 207 int literal_bytes = 0; 208 for (int i = 0; i < this->table_size(); ++i) { 209 int count = 0; 210 for (HashtableEntry<T, F>* e = this->bucket(i); 211 e != NULL; e = e->next()) { 212 count++; 213 T l = (literal_load_barrier != NULL) ? literal_load_barrier(e) : e->literal(); 214 literal_bytes += literal_size(l); 215 } 216 summary.add((double)count); 217 } 218 double num_buckets = summary.num(); 219 double num_entries = summary.sum(); 220 221 int bucket_bytes = (int)num_buckets * sizeof(HashtableBucket<F>); 222 int entry_bytes = (int)num_entries * sizeof(HashtableEntry<T, F>); 223 int total_bytes = literal_bytes + bucket_bytes + entry_bytes; 224 225 int bucket_size = (num_buckets <= 0) ? 0 : (bucket_bytes / num_buckets); 226 int entry_size = (num_entries <= 0) ? 0 : (entry_bytes / num_entries); 227 228 st->print_cr("%s statistics:", table_name); 229 st->print_cr("Number of buckets : %9d = %9d bytes, each %d", (int)num_buckets, bucket_bytes, bucket_size); 230 st->print_cr("Number of entries : %9d = %9d bytes, each %d", (int)num_entries, entry_bytes, entry_size); 231 if (literal_bytes != 0) { 232 double literal_avg = (num_entries <= 0) ? 0 : (literal_bytes / num_entries); 233 st->print_cr("Number of literals : %9d = %9d bytes, avg %7.3f", (int)num_entries, literal_bytes, literal_avg); 234 } 235 st->print_cr("Total footprint : %9s = %9d bytes", "", total_bytes); 236 st->print_cr("Average bucket size : %9.3f", summary.avg()); 237 st->print_cr("Variance of bucket size : %9.3f", summary.variance()); 238 st->print_cr("Std. dev. of bucket size: %9.3f", summary.sd()); 239 st->print_cr("Maximum bucket size : %9d", (int)summary.maximum()); 240 } 241 242 #ifndef PRODUCT 243 template <class T> void print_literal(T l) { 244 l->print(); 245 } 246 247 static void print_literal(WeakHandle<vm_class_loader_data> l) { 248 l.print(); 249 } 250 251 template <class T, MEMFLAGS F> void Hashtable<T, F>::print() { 252 ResourceMark rm; 253 254 for (int i = 0; i < BasicHashtable<F>::table_size(); i++) { 255 HashtableEntry<T, F>* entry = bucket(i); 256 while(entry != NULL) { 257 tty->print("%d : ", i); 258 print_literal(entry->literal()); 259 tty->cr(); | 174 // Switch to the new storage 175 _buckets = buckets_new; 176 177 return true; 178 } 179 180 template <MEMFLAGS F> bool BasicHashtable<F>::maybe_grow(int max_size, int load_factor) { 181 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); 182 183 if (table_size() >= max_size) { 184 return false; 185 } 186 if (number_of_entries() / table_size() > load_factor) { 187 resize(MIN2<int>(table_size() * 2, max_size)); 188 return true; 189 } else { 190 return false; 191 } 192 } 193 194 template <class T, MEMFLAGS F> TableStatistics Hashtable<T, F>::statistics_calculate(T (*literal_load_barrier)(HashtableEntry<T, F>*)) { 195 NumberSeq summary; 196 int literal_bytes = 0; 197 for (int i = 0; i < this->table_size(); ++i) { 198 int count = 0; 199 for (HashtableEntry<T, F>* e = this->bucket(i); 200 e != NULL; e = e->next()) { 201 count++; 202 T l = (literal_load_barrier != NULL) ? literal_load_barrier(e) : e->literal(); 203 literal_bytes += literal_size(l); 204 } 205 summary.add((double)count); 206 } 207 return TableStatistics(this->_stats_rate, summary, literal_bytes, sizeof(HashtableBucket<F>), sizeof(HashtableEntry<T, F>)); 208 } 209 210 // Dump footprint and bucket length statistics 211 // 212 // Note: if you create a new subclass of Hashtable<MyNewType, F>, you will need to 213 // add a new function static int literal_size(MyNewType lit) 214 // because I can't get template <class T> int literal_size(T) to pick the specializations for Symbol and oop. 215 template <class T, MEMFLAGS F> void Hashtable<T, F>::print_table_statistics(outputStream* st, 216 const char *table_name, 217 T (*literal_load_barrier)(HashtableEntry<T, F>*)) { 218 TableStatistics ts = statistics_calculate(literal_load_barrier); 219 ts.print(st, table_name); 220 } 221 222 #ifndef PRODUCT 223 template <class T> void print_literal(T l) { 224 l->print(); 225 } 226 227 static void print_literal(WeakHandle<vm_class_loader_data> l) { 228 l.print(); 229 } 230 231 template <class T, MEMFLAGS F> void Hashtable<T, F>::print() { 232 ResourceMark rm; 233 234 for (int i = 0; i < BasicHashtable<F>::table_size(); i++) { 235 HashtableEntry<T, F>* entry = bucket(i); 236 while(entry != NULL) { 237 tty->print("%d : ", i); 238 print_literal(entry->literal()); 239 tty->cr(); |