8014262: PrintStringTableStatistics should include more footprint info

Sat, 18 May 2013 20:41:01 -0700

author
iklam
date
Sat, 18 May 2013 20:41:01 -0700
changeset 5144
a5d6f0c3585f
parent 5143
386b77bf6427
child 5145
5e3573e08a83

8014262: PrintStringTableStatistics should include more footprint info
Summary: Added info for the string/symbol objects and the hash entries
Reviewed-by: coleenp, rbackman

src/share/vm/classfile/symbolTable.cpp file | annotate | diff | comparison | revisions
src/share/vm/utilities/hashtable.cpp file | annotate | diff | comparison | revisions
src/share/vm/utilities/hashtable.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/classfile/symbolTable.cpp	Fri May 17 17:52:07 2013 -0700
     1.2 +++ b/src/share/vm/classfile/symbolTable.cpp	Sat May 18 20:41:01 2013 -0700
     1.3 @@ -35,7 +35,6 @@
     1.4  #include "oops/oop.inline2.hpp"
     1.5  #include "runtime/mutexLocker.hpp"
     1.6  #include "utilities/hashtable.inline.hpp"
     1.7 -#include "utilities/numberSeq.hpp"
     1.8  
     1.9  // --------------------------------------------------------------------------
    1.10  
    1.11 @@ -451,21 +450,7 @@
    1.12  }
    1.13  
    1.14  void SymbolTable::dump(outputStream* st) {
    1.15 -  NumberSeq summary;
    1.16 -  for (int i = 0; i < the_table()->table_size(); ++i) {
    1.17 -    int count = 0;
    1.18 -    for (HashtableEntry<Symbol*, mtSymbol>* e = the_table()->bucket(i);
    1.19 -       e != NULL; e = e->next()) {
    1.20 -      count++;
    1.21 -    }
    1.22 -    summary.add((double)count);
    1.23 -  }
    1.24 -  st->print_cr("SymbolTable statistics:");
    1.25 -  st->print_cr("Number of buckets       : %7d", summary.num());
    1.26 -  st->print_cr("Average bucket size     : %7.0f", summary.avg());
    1.27 -  st->print_cr("Variance of bucket size : %7.0f", summary.variance());
    1.28 -  st->print_cr("Std. dev. of bucket size: %7.0f", summary.sd());
    1.29 -  st->print_cr("Maximum bucket size     : %7.0f", summary.maximum());
    1.30 +  the_table()->dump_table(st, "SymbolTable");
    1.31  }
    1.32  
    1.33  
    1.34 @@ -814,21 +799,7 @@
    1.35  }
    1.36  
    1.37  void StringTable::dump(outputStream* st) {
    1.38 -  NumberSeq summary;
    1.39 -  for (int i = 0; i < the_table()->table_size(); ++i) {
    1.40 -    HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
    1.41 -    int count = 0;
    1.42 -    for ( ; p != NULL; p = p->next()) {
    1.43 -      count++;
    1.44 -    }
    1.45 -    summary.add((double)count);
    1.46 -  }
    1.47 -  st->print_cr("StringTable statistics:");
    1.48 -  st->print_cr("Number of buckets       : %7d", summary.num());
    1.49 -  st->print_cr("Average bucket size     : %7.0f", summary.avg());
    1.50 -  st->print_cr("Variance of bucket size : %7.0f", summary.variance());
    1.51 -  st->print_cr("Std. dev. of bucket size: %7.0f", summary.sd());
    1.52 -  st->print_cr("Maximum bucket size     : %7.0f", summary.maximum());
    1.53 +  the_table()->dump_table(st, "StringTable");
    1.54  }
    1.55  
    1.56  
     2.1 --- a/src/share/vm/utilities/hashtable.cpp	Fri May 17 17:52:07 2013 -0700
     2.2 +++ b/src/share/vm/utilities/hashtable.cpp	Sat May 18 20:41:01 2013 -0700
     2.3 @@ -33,6 +33,7 @@
     2.4  #include "utilities/dtrace.hpp"
     2.5  #include "utilities/hashtable.hpp"
     2.6  #include "utilities/hashtable.inline.hpp"
     2.7 +#include "utilities/numberSeq.hpp"
     2.8  
     2.9  
    2.10  // This is a generic hashtable, designed to be used for the symbol
    2.11 @@ -237,6 +238,57 @@
    2.12    }
    2.13  }
    2.14  
    2.15 +template <class T, MEMFLAGS F> int Hashtable<T, F>::literal_size(Symbol *symbol) {
    2.16 +  return symbol->size() * HeapWordSize;
    2.17 +}
    2.18 +
    2.19 +template <class T, MEMFLAGS F> int Hashtable<T, F>::literal_size(oop oop) {
    2.20 +  // NOTE: this would over-count if (pre-JDK8) java_lang_Class::has_offset_field() is true,
    2.21 +  // and the String.value array is shared by several Strings. However, starting from JDK8,
    2.22 +  // the String.value array is not shared anymore.
    2.23 +  assert(oop != NULL && oop->klass() == SystemDictionary::String_klass(), "only strings are supported");
    2.24 +  return (oop->size() + java_lang_String::value(oop)->size()) * HeapWordSize;
    2.25 +}
    2.26 +
    2.27 +// Dump footprint and bucket length statistics
    2.28 +//
    2.29 +// Note: if you create a new subclass of Hashtable<MyNewType, F>, you will need to
    2.30 +// add a new function Hashtable<T, F>::literal_size(MyNewType lit)
    2.31 +
    2.32 +template <class T, MEMFLAGS F> void Hashtable<T, F>::dump_table(outputStream* st, const char *table_name) {
    2.33 +  NumberSeq summary;
    2.34 +  int literal_bytes = 0;
    2.35 +  for (int i = 0; i < this->table_size(); ++i) {
    2.36 +    int count = 0;
    2.37 +    for (HashtableEntry<T, F>* e = bucket(i);
    2.38 +       e != NULL; e = e->next()) {
    2.39 +      count++;
    2.40 +      literal_bytes += literal_size(e->literal());
    2.41 +    }
    2.42 +    summary.add((double)count);
    2.43 +  }
    2.44 +  double num_buckets = summary.num();
    2.45 +  double num_entries = summary.sum();
    2.46 +
    2.47 +  int bucket_bytes = (int)num_buckets * sizeof(bucket(0));
    2.48 +  int entry_bytes  = (int)num_entries * sizeof(HashtableEntry<T, F>);
    2.49 +  int total_bytes = literal_bytes +  bucket_bytes + entry_bytes;
    2.50 +
    2.51 +  double bucket_avg  = (num_buckets <= 0) ? 0 : (bucket_bytes  / num_buckets);
    2.52 +  double entry_avg   = (num_entries <= 0) ? 0 : (entry_bytes   / num_entries);
    2.53 +  double literal_avg = (num_entries <= 0) ? 0 : (literal_bytes / num_entries);
    2.54 +
    2.55 +  st->print_cr("%s statistics:", table_name);
    2.56 +  st->print_cr("Number of buckets       : %9d = %9d bytes, avg %7.3f", (int)num_buckets, bucket_bytes,  bucket_avg);
    2.57 +  st->print_cr("Number of entries       : %9d = %9d bytes, avg %7.3f", (int)num_entries, entry_bytes,   entry_avg);
    2.58 +  st->print_cr("Number of literals      : %9d = %9d bytes, avg %7.3f", (int)num_entries, literal_bytes, literal_avg);
    2.59 +  st->print_cr("Total footprint         : %9s = %9d bytes", "", total_bytes);
    2.60 +  st->print_cr("Average bucket size     : %9.3f", summary.avg());
    2.61 +  st->print_cr("Variance of bucket size : %9.3f", summary.variance());
    2.62 +  st->print_cr("Std. dev. of bucket size: %9.3f", summary.sd());
    2.63 +  st->print_cr("Maximum bucket size     : %9d", (int)summary.maximum());
    2.64 +}
    2.65 +
    2.66  
    2.67  // Dump the hash table buckets.
    2.68  
     3.1 --- a/src/share/vm/utilities/hashtable.hpp	Fri May 17 17:52:07 2013 -0700
     3.2 +++ b/src/share/vm/utilities/hashtable.hpp	Sat May 18 20:41:01 2013 -0700
     3.3 @@ -282,6 +282,19 @@
     3.4    static bool use_alternate_hashcode()  { return _seed != 0; }
     3.5    static jint seed()                    { return _seed; }
     3.6  
     3.7 +  static int literal_size(Symbol *symbol);
     3.8 +  static int literal_size(oop oop);
     3.9 +
    3.10 +  // The following two are currently not used, but are needed anyway because some
    3.11 +  // C++ compilers (MacOS and Solaris) force the instantiation of
    3.12 +  // Hashtable<ConstantPool*, mtClass>::dump_table() even though we never call this function
    3.13 +  // in the VM code.
    3.14 +  static int literal_size(ConstantPool *cp) {Unimplemented(); return 0;}
    3.15 +  static int literal_size(Klass *k)         {Unimplemented(); return 0;}
    3.16 +
    3.17 +public:
    3.18 +  void dump_table(outputStream* st, const char *table_name);
    3.19 +
    3.20   private:
    3.21    static jint _seed;
    3.22  };

mercurial