Skip to content

Commit

Permalink
[optimisation] Lazy initialisation of Modules Dependency Graph
Browse files Browse the repository at this point in the history
  • Loading branch information
adamretter committed Jul 31, 2023
1 parent 378af4d commit a97ecdc
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 25 deletions.
3 changes: 1 addition & 2 deletions exist-core/src/main/java/org/exist/xquery/ModuleContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ public ModuleContext(final XQueryContext parentContext, final String moduleNames
super(parentContext != null ? parentContext.db : null,
parentContext != null ? parentContext.getConfiguration() : null,
null,
false,
null);
false);
this.moduleNamespace = moduleNamespace;
this.modulePrefix = modulePrefix;
this.location = location;
Expand Down
52 changes: 29 additions & 23 deletions exist-core/src/main/java/org/exist/xquery/XQueryContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
import org.exist.xquery.update.Modification;
import org.exist.xquery.util.SerializerUtils;
import org.exist.xquery.value.*;
import org.jgrapht.Graph;
import org.jgrapht.alg.interfaces.ShortestPathAlgorithm;
import org.jgrapht.alg.shortestpath.TransitNodeRoutingShortestPath;
import org.jgrapht.graph.DefaultEdge;
Expand Down Expand Up @@ -234,7 +235,8 @@ public class XQueryContext implements BinaryValueManager, Context {
/**
* Describes a graph of all the modules and how they import each other.
*/
private @Nullable final FastutilMapGraph<ModuleVertex, DefaultEdge> modulesDependencyGraph;
private @Nullable Graph<ModuleVertex, DefaultEdge> modulesDependencyGraph;
private @Nullable ThreadPoolExecutor modulesDependencyGraphSPExecutor;

/**
* Used to save current state when modules are imported dynamically
Expand Down Expand Up @@ -466,10 +468,6 @@ public XQueryContext(@Nullable final Database db, @Nullable final Configuration
}

protected XQueryContext(@Nullable final Database db, @Nullable final Configuration configuration, @Nullable final Profiler profiler, final boolean loadDefaults) {
this(db, configuration, profiler, loadDefaults, new FastutilMapGraph<>(null, SupplierUtil.createDefaultEdgeSupplier(), DefaultGraphType.directedPseudograph().asUnweighted()));
}

protected XQueryContext(@Nullable final Database db, @Nullable final Configuration configuration, @Nullable final Profiler profiler, final boolean loadDefaults, final @Nullable FastutilMapGraph<ModuleVertex, DefaultEdge> modulesDependencyGraph) {
this.db = db;

// if needed, fallback to db.getConfiguration
Expand All @@ -490,8 +488,6 @@ protected XQueryContext(@Nullable final Database db, @Nullable final Configurati
this.profiler = new Profiler(null);
}

this.modulesDependencyGraph = modulesDependencyGraph;

this.watchdog = new XQueryWatchDog(this);

// load configuration defaults
Expand Down Expand Up @@ -1435,6 +1431,15 @@ public void reset(final boolean keepGlobals) {
httpContext = null;
}

if (modulesDependencyGraphSPExecutor != null) {
try {
ConcurrencyUtil.shutdownExecutionService(modulesDependencyGraphSPExecutor);
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
}
modulesDependencyGraphSPExecutor = null;
}

analyzed = false;
}

Expand Down Expand Up @@ -1524,13 +1529,21 @@ public void addModule(final String namespaceURI, final Module module) {
addRootModule(namespaceURI, module);
}

private Graph<ModuleVertex, DefaultEdge> getModulesDependencyGraph() {
// NOTE(AR) intentionally lazily initialised!
if (modulesDependencyGraph == null) {
this.modulesDependencyGraph = new FastutilMapGraph<>(null, SupplierUtil.createDefaultEdgeSupplier(), DefaultGraphType.directedPseudograph().asUnweighted());
}
return modulesDependencyGraph;
}

/**
* Add a vertex to the Modules Dependency Graph.
*
* @param moduleVertex the module vertex
*/
protected void addModuleVertex(final ModuleVertex moduleVertex) {
modulesDependencyGraph.addVertex(moduleVertex);
getModulesDependencyGraph().addVertex(moduleVertex);
}

/**
Expand All @@ -1541,7 +1554,7 @@ protected void addModuleVertex(final ModuleVertex moduleVertex) {
* @return true if the module vertex exists, false otherwise
*/
protected boolean hasModuleVertex(final ModuleVertex moduleVertex) {
return modulesDependencyGraph.containsVertex(moduleVertex);
return getModulesDependencyGraph().containsVertex(moduleVertex);
}

/**
Expand All @@ -1551,7 +1564,7 @@ protected boolean hasModuleVertex(final ModuleVertex moduleVertex) {
* @param sink the imported module
*/
protected void addModuleEdge(final ModuleVertex source, final ModuleVertex sink) {
modulesDependencyGraph.addEdge(source, sink);
getModulesDependencyGraph().addEdge(source, sink);
}

/**
Expand All @@ -1567,20 +1580,13 @@ protected boolean hasModulePath(final ModuleVertex source, final ModuleVertex si
return false;
}

ThreadPoolExecutor executor = null;
try {
executor = ConcurrencyUtil.createThreadPoolExecutor(2);
final ShortestPathAlgorithm<ModuleVertex, DefaultEdge> spa = new TransitNodeRoutingShortestPath<>(modulesDependencyGraph, executor);
return spa.getPath(source, sink) != null;
} finally {
if (executor != null) {
try {
ConcurrencyUtil.shutdownExecutionService(executor);
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
}
}
// NOTE(AR) intentionally lazily initialised!
if (modulesDependencyGraphSPExecutor == null) {
modulesDependencyGraphSPExecutor = ConcurrencyUtil.createThreadPoolExecutor(2);
}

final ShortestPathAlgorithm<ModuleVertex, DefaultEdge> spa = new TransitNodeRoutingShortestPath<>(getModulesDependencyGraph(), modulesDependencyGraphSPExecutor);
return spa.getPath(source, sink) != null;
}

protected void setRootModules(final String namespaceURI, @Nullable final Module[] modules) {
Expand Down

0 comments on commit a97ecdc

Please sign in to comment.