Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 4 commits into from Dec 18, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/org/jruby/RubyArray.java
Expand Up @@ -416,8 +416,8 @@ public IRubyObject[] toJavaArrayUnsafe() {


public IRubyObject[] toJavaArrayMaybeUnsafe() { public IRubyObject[] toJavaArrayMaybeUnsafe() {
return (!isShared && begin == 0 && values.length == realLength) ? values : toJavaArray(); return (!isShared && begin == 0 && values.length == realLength) ? values : toJavaArray();
} }

/** rb_ary_make_shared /** rb_ary_make_shared
* *
*/ */
Expand Down
39 changes: 36 additions & 3 deletions src/org/jruby/runtime/load/LoadService.java
Expand Up @@ -43,10 +43,12 @@
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import java.util.jar.JarFile; import java.util.jar.JarFile;
Expand Down Expand Up @@ -204,6 +206,8 @@ public String[] getSuffixes() {


protected RubyArray loadPath; protected RubyArray loadPath;
protected StringArraySet loadedFeatures; 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, Library> builtinLibraries = new HashMap<String, Library>();


protected final Map<String, JarFile> jarFiles = new HashMap<String, JarFile>(); protected final Map<String, JarFile> jarFiles = new HashMap<String, JarFile>();
Expand Down Expand Up @@ -296,9 +300,20 @@ public void addPaths(String... additionalDirectories) {
addPath(dir); 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)); 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) { protected void addPath(String path) {
Expand Down Expand Up @@ -536,7 +551,7 @@ private boolean smartLoadInternal(String file) {


boolean loaded = tryLoadingLibraryOrScript(runtime, state); boolean loaded = tryLoadingLibraryOrScript(runtime, state);
if (loaded) { if (loaded) {
addLoadedFeature(state.loadName); addLoadedFeature(file, state.loadName);
} }
return loaded; return loaded;
} }
Expand Down Expand Up @@ -627,9 +642,27 @@ public void removeInternalLoadedFeature(String name) {
RubyString nameRubyString = runtime.newString(name); RubyString nameRubyString = runtime.newString(name);
loadedFeatures.delete(runtime.getCurrentContext(), nameRubyString, Block.NULL_BLOCK); 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) { 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) { protected boolean isJarfileLibrary(SearchState state, final String file) {
Expand Down