mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
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:
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user