HADOOP-6502. Improve the performance of Configuration.getClassByName when the class is not found by caching negative results. Contributed by Sharad Agarwal and Todd Lipcon.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-0.23@1244619 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Todd Lipcon 2012-02-15 18:10:05 +00:00
parent 9ea26a7b08
commit 7565d7c5cd
3 changed files with 44 additions and 11 deletions

View File

@ -17,6 +17,10 @@ Release 0.23.2 - UNRELEASED
HADOOP-8071. Avoid an extra packet in client code when nagling is HADOOP-8071. Avoid an extra packet in client code when nagling is
disabled. (todd) disabled. (todd)
HADOOP-6502. Improve the performance of Configuration.getClassByName when
the class is not found by caching negative results.
(sharad, todd via todd)
BUG FIXES BUG FIXES
HADOOP-8042 When copying a file out of HDFS, modifying it, and uploading HADOOP-8042 When copying a file out of HDFS, modifying it, and uploading

View File

@ -1146,6 +1146,22 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
* @throws ClassNotFoundException if the class is not found. * @throws ClassNotFoundException if the class is not found.
*/ */
public Class<?> getClassByName(String name) throws ClassNotFoundException { public Class<?> getClassByName(String name) throws ClassNotFoundException {
Class<?> ret = getClassByNameOrNull(name);
if (ret == null) {
throw new ClassNotFoundException("Class " + name + " not found");
}
return ret;
}
/**
* Load a class by name, returning null rather than throwing an exception
* if it couldn't be loaded. This is to avoid the overhead of creating
* an exception.
*
* @param name the class name
* @return the class object, or null if it could not be found.
*/
public Class<?> getClassByNameOrNull(String name) {
Map<String, Class<?>> map; Map<String, Class<?>> map;
synchronized (CACHE_CLASSES) { synchronized (CACHE_CLASSES) {
@ -1157,12 +1173,20 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
} }
} }
Class<?> clazz = map.get(name); Class<?> clazz = null;
if (clazz == null) { if (!map.containsKey(name)) {
clazz = Class.forName(name, true, classLoader); try {
if (clazz != null) { clazz = Class.forName(name, true, classLoader);
// two putters can race here, but they'll put the same class } catch (ClassNotFoundException e) {
map.put(name, clazz); map.put(name, null); //cache negative that class is not found
return null;
}
// two putters can race here, but they'll put the same class
map.put(name, clazz);
} else { // check already performed on this class name
clazz = map.get(name);
if (clazz == null) { // found the negative
return null;
} }
} }

View File

@ -86,17 +86,22 @@ public class ReflectionUtils {
//invoke configure on theObject //invoke configure on theObject
try { try {
Class<?> jobConfClass = Class<?> jobConfClass =
conf.getClassByName("org.apache.hadoop.mapred.JobConf"); conf.getClassByNameOrNull("org.apache.hadoop.mapred.JobConf");
if (jobConfClass == null) {
return;
}
Class<?> jobConfigurableClass = Class<?> jobConfigurableClass =
conf.getClassByName("org.apache.hadoop.mapred.JobConfigurable"); conf.getClassByNameOrNull("org.apache.hadoop.mapred.JobConfigurable");
if (jobConfClass.isAssignableFrom(conf.getClass()) && if (jobConfigurableClass == null) {
return;
}
if (jobConfClass.isAssignableFrom(conf.getClass()) &&
jobConfigurableClass.isAssignableFrom(theObject.getClass())) { jobConfigurableClass.isAssignableFrom(theObject.getClass())) {
Method configureMethod = Method configureMethod =
jobConfigurableClass.getMethod("configure", jobConfClass); jobConfigurableClass.getMethod("configure", jobConfClass);
configureMethod.invoke(theObject, conf); configureMethod.invoke(theObject, conf);
} }
} catch (ClassNotFoundException e) {
//JobConf/JobConfigurable not in classpath. no need to configure
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("Error in configuring object", e); throw new RuntimeException("Error in configuring object", e);
} }