Skip to content

Commit 3029589

Browse files
committed
Support bulk removal of figures
1 parent ae2c7d0 commit 3029589

File tree

4 files changed

+158
-53
lines changed

4 files changed

+158
-53
lines changed

visualizer/IdealGraphVisualizer/Graph/src/main/java/org/graalvm/visualizer/graph/Connection.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.awt.Point;
3030
import java.util.ArrayList;
3131
import java.util.Collections;
32+
import java.util.HashSet;
3233
import java.util.List;
3334

3435
public final class Connection implements Link {
@@ -141,6 +142,22 @@ public void remove() {
141142
outputSlot.connections.remove(this);
142143
}
143144

145+
/**
146+
* When removing large numbers of figures, repeatedly removing individual edges becomes n squared because
147+
* of the use of ArrayList. If the {@code cleaned} map is passed in then the Figures to be removed have been marked
148+
* with {@link Figure#isDeleted()}. The lists of successor, predecessors and connections are then just cleaned once.
149+
*/
150+
public void remove(HashSet<Object> cleaned) {
151+
if (cleaned == null) {
152+
remove();
153+
return;
154+
}
155+
156+
inputSlot.cleanDeletedFigures(cleaned);
157+
outputSlot.cleanDeletedFigures(cleaned);
158+
}
159+
160+
144161
public String getToolTipText() {
145162
StringBuilder builder = new StringBuilder();
146163
if (label != null) {

visualizer/IdealGraphVisualizer/Graph/src/main/java/org/graalvm/visualizer/graph/Diagram.java

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,35 @@
2222
*/
2323
package org.graalvm.visualizer.graph;
2424

25-
import static jdk.graal.compiler.graphio.parsing.model.KnownPropertyNames.PROPNAME_NAME;
26-
import static jdk.graal.compiler.graphio.parsing.model.KnownPropertyValues.NAME_ROOT;
27-
import static jdk.graal.compiler.graphio.parsing.model.KnownPropertyValues.NAME_START;
25+
import jdk.graal.compiler.graphio.parsing.model.InputBlock;
26+
import jdk.graal.compiler.graphio.parsing.model.InputEdge;
27+
import jdk.graal.compiler.graphio.parsing.model.InputGraph;
28+
import jdk.graal.compiler.graphio.parsing.model.InputNode;
29+
import jdk.graal.compiler.graphio.parsing.model.Properties;
30+
import jdk.graal.compiler.graphio.parsing.model.Properties.EqualityPropertyMatcher;
31+
import org.graalvm.visualizer.data.Source;
2832

29-
import java.awt.*;
30-
import java.util.*;
33+
import java.awt.Dimension;
34+
import java.awt.Font;
35+
import java.util.ArrayList;
36+
import java.util.Collection;
37+
import java.util.Collections;
38+
import java.util.HashMap;
39+
import java.util.HashSet;
40+
import java.util.LinkedHashMap;
3141
import java.util.List;
42+
import java.util.Map;
43+
import java.util.Optional;
44+
import java.util.Set;
3245
import java.util.concurrent.Callable;
3346
import java.util.concurrent.locks.Lock;
3447
import java.util.concurrent.locks.ReadWriteLock;
3548
import java.util.concurrent.locks.ReentrantReadWriteLock;
3649
import java.util.stream.Stream;
3750

38-
import org.graalvm.visualizer.data.Source;
39-
40-
import jdk.graal.compiler.graphio.parsing.model.*;
41-
import jdk.graal.compiler.graphio.parsing.model.Properties;
42-
import jdk.graal.compiler.graphio.parsing.model.Properties.EqualityPropertyMatcher;
51+
import static jdk.graal.compiler.graphio.parsing.model.KnownPropertyNames.PROPNAME_NAME;
52+
import static jdk.graal.compiler.graphio.parsing.model.KnownPropertyValues.NAME_ROOT;
53+
import static jdk.graal.compiler.graphio.parsing.model.KnownPropertyValues.NAME_START;
4354

4455
/**
4556
* Visual model of an {@link InputGraph}. Captures positions, sizes, routing
@@ -319,20 +330,18 @@ public static Diagram createDiagram(InputGraph graph, String nodeText) {
319330
return d;
320331
}
321332

322-
public void removeAllFigures(Collection<Figure> figuresToRemove) {
323-
if (figuresToRemove instanceof Set) {
324-
removeAllFigures(((Set) figuresToRemove));
325-
}
326-
Set s = new HashSet<>(figuresToRemove);
327-
removeAllFigures(s);
328-
}
329-
330333
public void removeAllFigures(Set<Figure> figuresToRemove) {
331334
if (!figuresToRemove.isEmpty()) {
332335
invalidateSlotMap();
333336
}
337+
// First mark all Figures to be deleted
338+
for (Figure f : figuresToRemove) {
339+
f.setDeleted();
340+
}
341+
// Now remove the edges associated with the deleted figures
342+
HashSet<Object> cleaned = new HashSet<>();
334343
for (Figure f : figuresToRemove) {
335-
freeFigure(f);
344+
freeFigure(f, cleaned);
336345
}
337346

338347
for (Figure f : figuresToRemove) {
@@ -348,16 +357,21 @@ private Set<Integer> collectFigureIds(Figure succ) {
348357
return representedIds;
349358
}
350359

351-
private void freeFigure(Figure succ) {
360+
private void freeFigure(Figure succ, HashSet<Object> cleaned) {
352361
Set<Integer> representedIds = sourceMap == null ? null : collectFigureIds(succ);
353362
List<InputSlot> inputSlots = new ArrayList<>(succ.getInputSlots());
354363
for (InputSlot s : inputSlots) {
355-
succ.removeInputSlot(s);
364+
succ.removeInputSlot(s, cleaned);
356365
}
357366

358367
List<OutputSlot> outputSlots = new ArrayList<>(succ.getOutputSlots());
359368
for (OutputSlot s : outputSlots) {
360-
succ.removeOutputSlot(s);
369+
succ.removeOutputSlot(s, cleaned);
370+
}
371+
372+
if (cleaned != null) {
373+
// When doing a bulk cleaning, the edges of deleted figures aren't directly updated so clear then here.
374+
succ.clear();
361375
}
362376

363377
assert succ.getInputSlots().isEmpty();
@@ -372,7 +386,7 @@ private void freeFigure(Figure succ) {
372386

373387
public void removeFigure(Figure succ) {
374388
assert this.figureMap.containsValue(succ);
375-
freeFigure(succ);
389+
freeFigure(succ, null);
376390
this.figureMap.remove(succ.getId());
377391
invalidateSlotMap();
378392
}

visualizer/IdealGraphVisualizer/Graph/src/main/java/org/graalvm/visualizer/graph/Figure.java

Lines changed: 71 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,31 @@
2222
*/
2323
package org.graalvm.visualizer.graph;
2424

25-
import static jdk.graal.compiler.graphio.parsing.model.KnownPropertyNames.PROPNAME_NAME;
26-
import static jdk.graal.compiler.graphio.parsing.model.KnownPropertyValues.NAME_ROOT;
27-
28-
import java.awt.*;
29-
import java.awt.image.BufferedImage;
30-
import java.util.*;
31-
import java.util.List;
32-
33-
import org.graalvm.visualizer.data.Source;
34-
import org.graalvm.visualizer.layout.Cluster;
35-
import org.graalvm.visualizer.layout.Vertex;
36-
3725
import jdk.graal.compiler.graphio.parsing.model.InputBlock;
3826
import jdk.graal.compiler.graphio.parsing.model.InputGraph;
3927
import jdk.graal.compiler.graphio.parsing.model.InputNode;
4028
import jdk.graal.compiler.graphio.parsing.model.Properties;
29+
import org.graalvm.visualizer.data.Source;
30+
import org.graalvm.visualizer.layout.Cluster;
31+
import org.graalvm.visualizer.layout.Vertex;
32+
33+
import java.awt.Color;
34+
import java.awt.Dimension;
35+
import java.awt.Font;
36+
import java.awt.FontMetrics;
37+
import java.awt.Graphics;
38+
import java.awt.Point;
39+
import java.awt.Rectangle;
40+
import java.awt.image.BufferedImage;
41+
import java.util.ArrayList;
42+
import java.util.Collection;
43+
import java.util.Collections;
44+
import java.util.HashSet;
45+
import java.util.List;
46+
import java.util.Set;
47+
48+
import static jdk.graal.compiler.graphio.parsing.model.KnownPropertyNames.PROPNAME_NAME;
49+
import static jdk.graal.compiler.graphio.parsing.model.KnownPropertyValues.NAME_ROOT;
4150

4251
public class Figure extends Properties.Entity implements Source.Provider, Vertex, DiagramItem {
4352
public static final int INSET = 8;
@@ -46,14 +55,14 @@ public class Figure extends Properties.Entity implements Source.Provider, Vertex
4655
public static final int SLOT_START = 4;
4756
public static final int SLOT_OFFSET = 8;
4857

49-
protected List<InputSlot> inputSlots;
58+
protected ArrayList<InputSlot> inputSlots;
5059
private OutputSlot singleOutput;
51-
private List<OutputSlot> outputSlots;
60+
private ArrayList<OutputSlot> outputSlots;
5261
private final Source source;
5362
private final Diagram diagram;
5463
private Point position;
55-
private final List<Figure> predecessors;
56-
private final List<Figure> successors;
64+
private final ArrayList<Figure> predecessors;
65+
private final ArrayList<Figure> successors;
5766
private List<InputGraph> subgraphs;
5867
private Color color;
5968
private final int id;
@@ -64,6 +73,39 @@ public class Figure extends Properties.Entity implements Source.Provider, Vertex
6473
private final int hash;
6574
private boolean boundary;
6675

76+
/**
77+
* Marked for bulk deletion.
78+
*/
79+
private boolean deleted;
80+
81+
void setDeleted() {
82+
this.deleted = true;
83+
}
84+
85+
boolean isDeleted() {
86+
return deleted;
87+
}
88+
89+
/**
90+
* Drop all edges when deleting a Figure.
91+
*/
92+
void clear() {
93+
assert isDeleted() : this;
94+
if (inputSlots != null) {
95+
inputSlots.clear();
96+
}
97+
if (outputSlots != null) {
98+
outputSlots.clear();
99+
}
100+
if (predecessors != null) {
101+
predecessors.clear();
102+
}
103+
if (successors != null) {
104+
successors.clear();
105+
}
106+
}
107+
108+
67109
/**
68110
* Visible flag
69111
*/
@@ -213,6 +255,14 @@ protected void addSuccessor(Figure f) {
213255
this.successors.add(f);
214256
}
215257

258+
/**
259+
* Clean up all edges which reference an {@link Figure#isDeleted()} figure.
260+
*/
261+
public void cleanDeletedFigures() {
262+
predecessors.removeIf(Figure::isDeleted);
263+
successors.removeIf(Figure::isDeleted);
264+
}
265+
216266
protected void removePredecessor(Figure f) {
217267
assert predecessors.contains(f);
218268
predecessors.remove(f);
@@ -372,13 +422,13 @@ public List<OutputSlot> getOutputSlots() {
372422
}
373423
}
374424

375-
void removeInputSlot(InputSlot s) {
376-
s.removeAllConnections();
425+
void removeInputSlot(InputSlot s, HashSet<Object> cleaned) {
426+
s.removeAllConnections(cleaned);
377427
inputSlots.remove(s);
378428
}
379429

380-
void removeOutputSlot(OutputSlot s) {
381-
s.removeAllConnections();
430+
void removeOutputSlot(OutputSlot s, HashSet<Object> cleaned) {
431+
s.removeAllConnections(cleaned);
382432
doRemoveOutputSlot(s);
383433
}
384434

@@ -545,4 +595,5 @@ private static void replaceFromTo(Figure from, Figure to) {
545595
public void replaceFrom(Figure source) {
546596
replaceFromTo(source, this);
547597
}
598+
548599
}

visualizer/IdealGraphVisualizer/Graph/src/main/java/org/graalvm/visualizer/graph/Slot.java

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,27 @@
2222
*/
2323
package org.graalvm.visualizer.graph;
2424

25-
import static jdk.graal.compiler.graphio.parsing.model.KnownPropertyNames.*;
25+
import jdk.graal.compiler.graphio.parsing.model.InputNode;
26+
import jdk.graal.compiler.graphio.parsing.model.Properties;
27+
import org.graalvm.visualizer.data.Source;
28+
import org.graalvm.visualizer.layout.Port;
29+
import org.graalvm.visualizer.layout.Vertex;
30+
import org.graalvm.visualizer.util.StringUtils;
2631

27-
import java.awt.*;
32+
import java.awt.Color;
33+
import java.awt.Font;
34+
import java.awt.FontMetrics;
35+
import java.awt.Graphics;
2836
import java.awt.image.BufferedImage;
2937
import java.util.ArrayList;
3038
import java.util.Collections;
3139
import java.util.Comparator;
40+
import java.util.HashSet;
3241
import java.util.List;
3342

34-
import org.graalvm.visualizer.data.Source;
35-
import org.graalvm.visualizer.layout.Port;
36-
import org.graalvm.visualizer.layout.Vertex;
37-
import org.graalvm.visualizer.util.StringUtils;
38-
39-
import jdk.graal.compiler.graphio.parsing.model.InputNode;
40-
import jdk.graal.compiler.graphio.parsing.model.Properties;
43+
import static jdk.graal.compiler.graphio.parsing.model.KnownPropertyNames.PROPNAME_CONNECTION_COUNT;
44+
import static jdk.graal.compiler.graphio.parsing.model.KnownPropertyNames.PROPNAME_FIGURE;
45+
import static jdk.graal.compiler.graphio.parsing.model.KnownPropertyNames.PROPNAME_NAME;
4146

4247
public abstract class Slot implements Port, Source.Provider, Properties.Provider {
4348

@@ -201,9 +206,13 @@ public List<Connection> getConnections() {
201206
}
202207

203208
public void removeAllConnections() {
209+
removeAllConnections(null);
210+
}
211+
212+
public void removeAllConnections(HashSet<Object> cleaned) {
204213
List<Connection> connectionsCopy = new ArrayList<>(this.connections);
205214
for (Connection c : connectionsCopy) {
206-
c.remove();
215+
c.remove(cleaned);
207216
}
208217
}
209218

@@ -212,4 +221,18 @@ public Vertex getVertex() {
212221
return figure;
213222
}
214223

224+
/**
225+
* Clean up all edges which reference an {@link Figure#isDeleted()} figure.
226+
*/
227+
void cleanDeletedFigures(HashSet<Object> cleaned) {
228+
Figure input = getFigure();
229+
if (!input.isDeleted()) {
230+
if (cleaned.add(input)) {
231+
input.cleanDeletedFigures();
232+
}
233+
}
234+
if (cleaned.add(this)) {
235+
this.connections.removeIf(x -> x.getInputSlot().getFigure().isDeleted() || x.getOutputSlot().getFigure().isDeleted());
236+
}
237+
}
215238
}

0 commit comments

Comments
 (0)