7114376: Make system dictionary hashtable bucket array size configurable
Summary: 7u4 new experimental flag -XX:PredictedClassLoadedCount=#
Reviewed-by: dholmes, phh, dcubed
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/LoaderConstraintTable.java Mon Jan 30 05:08:09 2012 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/LoaderConstraintTable.java Mon Jan 30 23:27:30 2012 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,15 +42,6 @@
private static synchronized void initialize(TypeDataBase db) {
Type type = db.lookupType("LoaderConstraintTable");
- nofBuckets = db.lookupIntConstant("LoaderConstraintTable::_nof_buckets").intValue();
- }
-
- // Fields
- private static int nofBuckets;
-
- // Accessors
- public static int getNumOfBuckets() {
- return nofBuckets;
}
public LoaderConstraintTable(Address addr) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java Mon Jan 30 05:08:09 2012 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java Mon Jan 30 23:27:30 2012 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,6 @@
private static AddressField placeholdersField;
private static AddressField loaderConstraintTableField;
private static sun.jvm.hotspot.types.OopField javaSystemLoaderField;
- private static int nofBuckets;
private static sun.jvm.hotspot.types.OopField objectKlassField;
private static sun.jvm.hotspot.types.OopField classLoaderKlassField;
@@ -62,7 +61,6 @@
placeholdersField = type.getAddressField("_placeholders");
loaderConstraintTableField = type.getAddressField("_loader_constraints");
javaSystemLoaderField = type.getOopField("_java_system_loader");
- nofBuckets = db.lookupIntConstant("SystemDictionary::_nof_buckets").intValue();
objectKlassField = type.getOopField(WK_KLASS("Object_klass"));
classLoaderKlassField = type.getOopField(WK_KLASS("ClassLoader_klass"));
@@ -142,10 +140,6 @@
return newOop(javaSystemLoaderField.getValue());
}
- public static int getNumOfBuckets() {
- return nofBuckets;
- }
-
private static Oop newOop(OopHandle handle) {
return VM.getVM().getObjectHeap().newOop(handle);
}
--- a/hotspot/src/share/vm/classfile/dictionary.cpp Mon Jan 30 05:08:09 2012 -0800
+++ b/hotspot/src/share/vm/classfile/dictionary.cpp Mon Jan 30 23:27:30 2012 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -618,7 +618,8 @@
ResourceMark rm;
HandleMark hm;
- tty->print_cr("Java system dictionary (classes=%d)", number_of_entries());
+ tty->print_cr("Java system dictionary (table_size=%d, classes=%d)",
+ table_size(), number_of_entries());
tty->print_cr("^ indicates that initiating loader is different from "
"defining loader");
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Mon Jan 30 05:08:09 2012 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Mon Jan 30 23:27:30 2012 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -64,6 +64,9 @@
int SystemDictionary::_number_of_modifications = 0;
+int SystemDictionary::_sdgeneration = 0;
+const int SystemDictionary::_primelist[_prime_array_size] = {1009,2017,4049,5051,10103,
+ 20201,40423,99991};
oop SystemDictionary::_system_loader_lock_obj = NULL;
@@ -1178,8 +1181,8 @@
klassOop SystemDictionary::find_shared_class(Symbol* class_name) {
if (shared_dictionary() != NULL) {
- unsigned int d_hash = dictionary()->compute_hash(class_name, Handle());
- int d_index = dictionary()->hash_to_index(d_hash);
+ unsigned int d_hash = shared_dictionary()->compute_hash(class_name, Handle());
+ int d_index = shared_dictionary()->hash_to_index(d_hash);
return shared_dictionary()->find_shared_class(d_index, d_hash, class_name);
} else {
return NULL;
@@ -1750,7 +1753,21 @@
placeholders()->oops_do(blk);
}
-
+// Calculate a "good" systemdictionary size based
+// on predicted or current loaded classes count
+int SystemDictionary::calculate_systemdictionary_size(int classcount) {
+ int newsize = _old_default_sdsize;
+ if ((classcount > 0) && !DumpSharedSpaces) {
+ int desiredsize = classcount/_average_depth_goal;
+ for (newsize = _primelist[_sdgeneration]; _sdgeneration < _prime_array_size -1;
+ newsize = _primelist[++_sdgeneration]) {
+ if (desiredsize <= newsize) {
+ break;
+ }
+ }
+ }
+ return newsize;
+}
bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive) {
bool result = dictionary()->do_unloading(is_alive);
constraints()->purge_loader_constraints(is_alive);
@@ -1873,7 +1890,8 @@
// Allocate arrays
assert(dictionary() == NULL,
"SystemDictionary should only be initialized once");
- _dictionary = new Dictionary(_nof_buckets);
+ _sdgeneration = 0;
+ _dictionary = new Dictionary(calculate_systemdictionary_size(PredictedLoadedClassCount));
_placeholders = new PlaceholderTable(_nof_buckets);
_number_of_modifications = 0;
_loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Mon Jan 30 05:08:09 2012 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Mon Jan 30 23:27:30 2012 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -346,6 +346,8 @@
// loaders. Returns "true" iff something was unloaded.
static bool do_unloading(BoolObjectClosure* is_alive);
+ static int calculate_systemdictionary_size(int loadedclasses);
+
// Applies "f->do_oop" to all root oops in the system dictionary.
static void oops_do(OopClosure* f);
@@ -538,12 +540,20 @@
_loader_constraint_size = 107, // number of entries in constraint table
_resolution_error_size = 107, // number of entries in resolution error table
_invoke_method_size = 139, // number of entries in invoke method table
- _nof_buckets = 1009 // number of buckets in hash table
+ _nof_buckets = 1009, // number of buckets in hash table for placeholders
+ _old_default_sdsize = 1009, // backward compat for system dictionary size
+ _prime_array_size = 8, // array of primes for system dictionary size
+ _average_depth_goal = 3 // goal for lookup length
};
// Static variables
+ // hashtable sizes for system dictionary to allow growth
+ // prime numbers for system dictionary size
+ static int _sdgeneration;
+ static const int _primelist[_prime_array_size];
+
// Hashtable holding loaded classes.
static Dictionary* _dictionary;
--- a/hotspot/src/share/vm/runtime/globals.hpp Mon Jan 30 05:08:09 2012 -0800
+++ b/hotspot/src/share/vm/runtime/globals.hpp Mon Jan 30 23:27:30 2012 -0500
@@ -1042,6 +1042,9 @@
notproduct(bool, PrintSystemDictionaryAtExit, false, \
"Prints the system dictionary at exit") \
\
+ experimental(intx, PredictedLoadedClassCount, 0, \
+ "Experimental: Tune loaded class cache starting size.") \
+ \
diagnostic(bool, UnsyncloadClass, false, \
"Unstable: VM calls loadClass unsynchronized. Custom " \
"class loader must call VM synchronized for findClass " \
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Jan 30 05:08:09 2012 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Jan 30 23:27:30 2012 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -2261,13 +2261,6 @@
\
declare_constant(SymbolTable::symbol_table_size) \
\
- /********************/ \
- /* SystemDictionary */ \
- /********************/ \
- \
- declare_constant(SystemDictionary::_loader_constraint_size) \
- declare_constant(SystemDictionary::_nof_buckets) \
- \
/***********************************/ \
/* LoaderConstraintTable constants */ \
/***********************************/ \
--- a/hotspot/src/share/vm/utilities/hashtable.hpp Mon Jan 30 05:08:09 2012 -0800
+++ b/hotspot/src/share/vm/utilities/hashtable.hpp Mon Jan 30 23:27:30 2012 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -183,7 +183,6 @@
// Accessor
int entry_size() const { return _entry_size; }
- int table_size() { return _table_size; }
// The following method is MT-safe and may be used with caution.
BasicHashtableEntry* bucket(int i);
@@ -195,6 +194,7 @@
BasicHashtableEntry* new_entry(unsigned int hashValue);
public:
+ int table_size() { return _table_size; }
void set_entry(int index, BasicHashtableEntry* entry);
void add_entry(int index, BasicHashtableEntry* entry);