From 1c86d5e8897d4e190376171ba4d78a943a412d46 Mon Sep 17 00:00:00 2001 From: Saurav Bhattacharya Date: Wed, 18 Mar 2026 19:41:35 -0700 Subject: [PATCH] =?UTF-8?q?perf:=20reduce=20computeStress()=20memory=20fro?= =?UTF-8?q?m=20O(V=C2=B2)=20to=20O(V)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous implementation pre-computed all-pairs BFS shortest paths into a Map> before iterating over pairs. For a graph with V vertices this allocates V HashMap instances with up to V entries each, plus V² boxed Integer objects — all held in memory simultaneously. This change computes BFS one source vertex at a time and discards the distance map after processing, keeping only one BFS result alive at any point. The algorithmic complexity is unchanged (still O(V*(V+E))) but peak heap usage drops from O(V²) to O(V+E), which matters for graphs with thousands of nodes where the stress metric is most useful. --- Gvisual/src/gvisual/ForceDirectedLayout.java | 21 +++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/Gvisual/src/gvisual/ForceDirectedLayout.java b/Gvisual/src/gvisual/ForceDirectedLayout.java index 06bb063..12068aa 100644 --- a/Gvisual/src/gvisual/ForceDirectedLayout.java +++ b/Gvisual/src/gvisual/ForceDirectedLayout.java @@ -514,21 +514,24 @@ public double computeStress() { int n = vertexList != null ? vertexList.size() : 0; if (n < 2) return 0; - // BFS shortest paths - Map> shortestPaths = - new HashMap>(); - for (String v : vertexList) { - shortestPaths.put(v, GraphUtils.bfsDistances(graph, v)); - } + // Ideal edge length: constant for this graph/layout + double k = Math.sqrt(width * height / n); + // Compute BFS one source at a time to reduce memory from O(V²) to O(V). + // The previous implementation stored all-pairs shortest paths in a + // Map> before iterating — for a graph + // with V vertices this allocates V HashMap instances with up to V + // entries each, plus V² Integer box objects. By computing BFS for + // vertex i, consuming distances to vertices j > i, and then + // discarding the map, we keep only one BFS result alive at a time. double stress = 0; double normalizer = 0; - // Ideal edge length: constant for this graph/layout, hoist out of loop - double k = Math.sqrt(width * height / n); + for (int i = 0; i < n; i++) { String vi = vertexList.get(i); double[] pi = positions.get(vi); - Map viPaths = shortestPaths.get(vi); + Map viPaths = GraphUtils.bfsDistances(graph, vi); + for (int j = i + 1; j < n; j++) { String vj = vertexList.get(j); Integer graphDist = viPaths.get(vj);