Skip to content

Implement loaded feature caching to reduce load path searching. #452

Merged
merged 4 commits into from Dec 18, 2012
View
4 src/org/jruby/RubyArray.java
@@ -416,8 +416,8 @@ public int getLength() {
public IRubyObject[] toJavaArrayMaybeUnsafe() {
return (!isShared && begin == 0 && values.length == realLength) ? values : toJavaArray();
- }
-
+ }
+
/** rb_ary_make_shared
*
*/
View
39 src/org/jruby/runtime/load/LoadService.java
@@ -43,10 +43,12 @@
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import java.util.jar.JarFile;
@@ -204,6 +206,8 @@
protected RubyArray loadPath;
protected StringArraySet loadedFeatures;
+ protected RubyArray loadedFeaturesDup;
+ private final Map<String, String> loadedFeaturesIndex = new ConcurrentHashMap<String, String>();
protected final Map<String, Library> builtinLibraries = new HashMap<String, Library>();
protected final Map<String, JarFile> jarFiles = new HashMap<String, JarFile>();
@@ -296,9 +300,20 @@ public void addPaths(String... additionalDirectories) {
addPath(dir);
}
}
+
+ protected boolean isFeatureInIndex(String shortName) {
+ return loadedFeaturesIndex.containsKey(shortName);
+ }
- protected void addLoadedFeature(String name) {
+ protected void addLoadedFeature(String shortName, String name) {
loadedFeatures.append(RubyString.newString(runtime, name));
+
+ addFeatureToIndex(shortName, name);
+ }
+
+ protected void addFeatureToIndex(String shortName, String name) {
+ loadedFeaturesDup = (RubyArray)loadedFeatures.dup();
+ loadedFeaturesIndex.put(shortName, name);
}
protected void addPath(String path) {
@@ -536,7 +551,7 @@ private boolean smartLoadInternal(String file) {
boolean loaded = tryLoadingLibraryOrScript(runtime, state);
if (loaded) {
- addLoadedFeature(state.loadName);
+ addLoadedFeature(file, state.loadName);
}
return loaded;
}
@@ -627,9 +642,27 @@ public void removeInternalLoadedFeature(String name) {
RubyString nameRubyString = runtime.newString(name);
loadedFeatures.delete(runtime.getCurrentContext(), nameRubyString, Block.NULL_BLOCK);
}
+
+ private boolean isFeaturesIndexUpToDate() {
+ // disable tracing during index check
+ runtime.getCurrentContext().preTrace();
+ try {
+ return loadedFeaturesDup != null && loadedFeaturesDup.eql(loadedFeatures);
+ } finally {
+ runtime.getCurrentContext().postTrace();
+ }
+ }
protected boolean featureAlreadyLoaded(String name) {
- return loadedFeatures.containsString(name);
+ if (loadedFeatures.containsString(name)) return true;
+
+ // Bail if our features index fell out of date.
+ if (!isFeaturesIndexUpToDate()) {
+ loadedFeaturesIndex.clear();
+ return false;
+ }
+
+ return isFeatureInIndex(name);
}
protected boolean isJarfileLibrary(SearchState state, final String file) {
Something went wrong with that request. Please try again.