src/share/vm/utilities/hashtable.cpp

changeset 5144
a5d6f0c3585f
parent 4037
da91efe96a93
child 5784
190899198332
     1.1 --- a/src/share/vm/utilities/hashtable.cpp	Fri May 17 17:52:07 2013 -0700
     1.2 +++ b/src/share/vm/utilities/hashtable.cpp	Sat May 18 20:41:01 2013 -0700
     1.3 @@ -33,6 +33,7 @@
     1.4  #include "utilities/dtrace.hpp"
     1.5  #include "utilities/hashtable.hpp"
     1.6  #include "utilities/hashtable.inline.hpp"
     1.7 +#include "utilities/numberSeq.hpp"
     1.8  
     1.9  
    1.10  // This is a generic hashtable, designed to be used for the symbol
    1.11 @@ -237,6 +238,57 @@
    1.12    }
    1.13  }
    1.14  
    1.15 +template <class T, MEMFLAGS F> int Hashtable<T, F>::literal_size(Symbol *symbol) {
    1.16 +  return symbol->size() * HeapWordSize;
    1.17 +}
    1.18 +
    1.19 +template <class T, MEMFLAGS F> int Hashtable<T, F>::literal_size(oop oop) {
    1.20 +  // NOTE: this would over-count if (pre-JDK8) java_lang_Class::has_offset_field() is true,
    1.21 +  // and the String.value array is shared by several Strings. However, starting from JDK8,
    1.22 +  // the String.value array is not shared anymore.
    1.23 +  assert(oop != NULL && oop->klass() == SystemDictionary::String_klass(), "only strings are supported");
    1.24 +  return (oop->size() + java_lang_String::value(oop)->size()) * HeapWordSize;
    1.25 +}
    1.26 +
    1.27 +// Dump footprint and bucket length statistics
    1.28 +//
    1.29 +// Note: if you create a new subclass of Hashtable<MyNewType, F>, you will need to
    1.30 +// add a new function Hashtable<T, F>::literal_size(MyNewType lit)
    1.31 +
    1.32 +template <class T, MEMFLAGS F> void Hashtable<T, F>::dump_table(outputStream* st, const char *table_name) {
    1.33 +  NumberSeq summary;
    1.34 +  int literal_bytes = 0;
    1.35 +  for (int i = 0; i < this->table_size(); ++i) {
    1.36 +    int count = 0;
    1.37 +    for (HashtableEntry<T, F>* e = bucket(i);
    1.38 +       e != NULL; e = e->next()) {
    1.39 +      count++;
    1.40 +      literal_bytes += literal_size(e->literal());
    1.41 +    }
    1.42 +    summary.add((double)count);
    1.43 +  }
    1.44 +  double num_buckets = summary.num();
    1.45 +  double num_entries = summary.sum();
    1.46 +
    1.47 +  int bucket_bytes = (int)num_buckets * sizeof(bucket(0));
    1.48 +  int entry_bytes  = (int)num_entries * sizeof(HashtableEntry<T, F>);
    1.49 +  int total_bytes = literal_bytes +  bucket_bytes + entry_bytes;
    1.50 +
    1.51 +  double bucket_avg  = (num_buckets <= 0) ? 0 : (bucket_bytes  / num_buckets);
    1.52 +  double entry_avg   = (num_entries <= 0) ? 0 : (entry_bytes   / num_entries);
    1.53 +  double literal_avg = (num_entries <= 0) ? 0 : (literal_bytes / num_entries);
    1.54 +
    1.55 +  st->print_cr("%s statistics:", table_name);
    1.56 +  st->print_cr("Number of buckets       : %9d = %9d bytes, avg %7.3f", (int)num_buckets, bucket_bytes,  bucket_avg);
    1.57 +  st->print_cr("Number of entries       : %9d = %9d bytes, avg %7.3f", (int)num_entries, entry_bytes,   entry_avg);
    1.58 +  st->print_cr("Number of literals      : %9d = %9d bytes, avg %7.3f", (int)num_entries, literal_bytes, literal_avg);
    1.59 +  st->print_cr("Total footprint         : %9s = %9d bytes", "", total_bytes);
    1.60 +  st->print_cr("Average bucket size     : %9.3f", summary.avg());
    1.61 +  st->print_cr("Variance of bucket size : %9.3f", summary.variance());
    1.62 +  st->print_cr("Std. dev. of bucket size: %9.3f", summary.sd());
    1.63 +  st->print_cr("Maximum bucket size     : %9d", (int)summary.maximum());
    1.64 +}
    1.65 +
    1.66  
    1.67  // Dump the hash table buckets.
    1.68  

mercurial