Check if a graph path already exists before adding one

Checking if a path exists is where sorting spends most of its time, and it gets slower the more edges the graph has, so avoid adding an edge between two plugins if there's already a path between them.

This improves sorting performance by 19%.

This doesn't add any additional path checks, as all the specific and hardcoded edges need to be added to ensure their validity (by then checking for cycles), and tie-breaking is more complicated so is worth dealing with separately.
This commit is contained in:
Oliver Hamlet
2025-01-18 09:39:20 +00:00
parent 0a61358b19
commit 628666e4ce
2 changed files with 24 additions and 2 deletions
+22 -2
View File
@@ -259,7 +259,7 @@ private:
for (const auto& toVertex : toPlugins) {
const auto& toPlugin = pluginGraph_->GetPlugin(toVertex);
if (!pluginGraph_->PathExists(toVertex, fromVertex)) {
if (!pluginGraph_->PathExistsInEitherDirection(toVertex, fromVertex)) {
const auto involvesUserMetadata = groupPathInvolvesUserMetadata ||
fromPlugin.IsGroupUserMetadata() ||
toPlugin.IsGroupUserMetadata();
@@ -738,6 +738,26 @@ bool PluginGraph::PathExists(const vertex_t& fromVertex,
return loot::FindPath(graph_, fromVertex, toVertex, visitor);
}
bool PluginGraph::PathExistsInEitherDirection(const vertex_t& vertex,
const vertex_t& otherVertex) {
if (pathsCache_.IsPathCached(vertex, otherVertex) ||
pathsCache_.IsPathCached(otherVertex, vertex)) {
return true;
}
{
PathCacher visitor(pathsCache_, vertex, otherVertex);
if (loot::FindPath(graph_, vertex, otherVertex, visitor)) {
return true;
}
}
PathCacher visitor(pathsCache_, otherVertex, vertex);
return loot::FindPath(graph_, otherVertex, vertex, visitor);
}
std::optional<std::vector<vertex_t>> PluginGraph::FindPath(
const vertex_t& fromVertex,
const vertex_t& toVertex) {
@@ -1032,7 +1052,7 @@ void PluginGraph::AddOverlapEdges() {
const auto fromVertex = thisPluginLoadsFirst ? vertex : otherVertex;
const auto toVertex = thisPluginLoadsFirst ? otherVertex : vertex;
if (!PathExists(toVertex, fromVertex)) {
if (!PathExistsInEitherDirection(toVertex, fromVertex)) {
AddEdge(fromVertex, toVertex, edgeType);
} else if (logger) {
logger->debug(
+2
View File
@@ -90,6 +90,8 @@ public:
bool EdgeExists(const vertex_t& fromVertex, const vertex_t& toVertex);
bool PathExists(const vertex_t& fromVertex, const vertex_t& toVertex);
bool PathExistsInEitherDirection(const vertex_t& vertex,
const vertex_t& otherVertex);
std::optional<std::vector<vertex_t>> FindPath(const vertex_t& fromVertex,
const vertex_t& toVertex);