You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -268,13 +284,13 @@ We will now go through the entire iongraph layout algorithm from start to finish
268
284
269
285
### Step 1: Layering
270
286
271
-
We first assign the basic blocks into horizontal tracks. This is very simple; we just start at layer 0 and recursively walk the graph, incrementing the layer number as we go. As we go, we track the "height" of each loop, not in pixels, but in layers.
287
+
We first sort the basic blocks into horizontal tracks called "layers". This is very simple; we just start at layer 0 and recursively walk the graph, incrementing the layer number as we go. As we go, we track the "height" of each loop, not in pixels, but in layers.
272
288
273
-
We also take this opportunity to start positioning nodes "inside" and "outside" of loops. Whenever we see an edge that exits a loop, we defer the layering of the destination block until we are done layering the loop contents, at which point we know the loop's height.
289
+
We also take this opportunity to vertically position nodes "inside" and "outside" of loops. Whenever we see an edge that exits a loop, we defer the layering of the destination block until we are done layering the loop contents, at which point we know the loop's height.
274
290
275
291
A note on implementation: nodes are visited multiple times throughout the process, not just once. This can produce a quadratic explosion for large graphs, but we find that an early-out is sufficient to avoid this problem in practice.
276
292
277
-
The animation below shows the layering algorithm in action. Notice how the final block in the graph is visited twice, once after each loop that branches to it, and in each case, the block is deferred until the entire loop has been layered. The final position of the block is below the entirety of both loops, rather than directly below one of its predecessors as Graphviz would do. (Remember, horizontal and vertical positions have not yet been computed; the positions of the blocks in this diagram are hardcoded for demonstration purposes.)
293
+
The animation below shows the layering algorithm in action. Notice how the final block in the graph is visited twice, once after each loop that branches to it, and in each case, the block is deferred until the entire loop has been layered, rather than processed immediately after its predecessor block. The final position of the block is below the entirety of both loops, rather than directly below one of its predecessors as Graphviz would do. (Remember, horizontal and vertical positions have not yet been computed; the positions of the blocks in this diagram are hardcoded for demonstration purposes.)
278
294
279
295
<details>
280
296
<summary>Implementation pseudocode</summary>
@@ -713,7 +729,7 @@ At the end of this step, all nodes have a fixed X-coordinate and will not be mod
@@ -1140,15 +1156,16 @@ The details of rendering are out of scope for this article, and depend on the sp
1140
1156
1141
1157
When rendering edges, we use a style inspired by [railroad diagrams](https://en.wikipedia.org/wiki/Syntax_diagram). These have many advantages over the Bézier curves employed by Graphviz. First, straight lines feel more organized and are easier to follow when scrolling up and down. Second, they are easy to route (vertical when crossing layers, horizontal between layers). Third, they are easy to coalesce when they share a destination, and the junctions provide a clear indication of the edge's direction. Fourth, they always cross at right angles, improving clarity and reducing the need to avoid edge crossings in the first place.
1142
1158
1143
-
Consider the following example. There are several edge crossings that may be considered undesirable, yet the edges and their directions remain clear. Of particular note is the vertical junction on the left: not only is it immediately clear that these edges share a destination, but the junction itself signals that the edges are flowing downward. We find this much more pleasant than the "rat's nest" that Graphviz tends to produce.
1159
+
Consider the following example. There are several edge crossings that may traditionally be considered undesirable—yet the edges and their directions remain clear. Of particular note is the vertical junction highlighted in red on the left: not only is it immediately clear that these edges share a destination, but the junction itself signals that the edges are flowing downward. We find this much more pleasant than the "rat's nest" that Graphviz tends to produce.
1160
+
1161
+
<img alt="Examples of railroad-diagram edges" src="/assets/img/iongraph-edge-examples-highlighted.png" width="716">
1144
1162
1145
-
<img alt="Examples of railroad-diagram edges" src="/assets/img/iongraph-edge-examples.png" width="716">
1146
1163
1147
1164
## Why does this work?
1148
1165
1149
1166
It may seem surprising that such a simple (and stupid) layout algorithm could produce such readable graphs, when more sophisticated layout algorithms struggle. However, we feel that the algorithm succeeds _because_ of its simplicity.
1150
1167
1151
-
Most graph layout algorithms are optimization problems, where error is minimized on some chosen metrics. However, these metrics seem to correlate poorly to readability inpractice. For example, it seems good in theory to rearrange nodes to minimize edge crossings. Butin practice, simple rules for edge routing seem to produce more readable results, and we achieve greater layout stability as a result.Similarly, layout rules like "align parents with their children" produce more readable results than "minimize the lengths of edges".
1168
+
Most graph layout algorithms are optimization problems, where error is minimized on some chosen metrics. However, these metrics seem to correlate poorly to readability inpractice. For example, it seems good in theory to rearrange nodes to minimize edge crossings. Buta predictable order of nodes seems to produce more sensible results overall, and simple rules for edge routing are sufficient to keep things tidy. (As a bonus, this also gives us layout stability from pass to pass.) Similarly, layout rules like "align parents with their children" produce more readable results than "minimize the lengths of edges".
1152
1169
1153
1170
Furthermore, by rejecting the optimization problem, a human author gains more control over the layout. We are able to position nodes "inside"of loops, and push post-loop content down in the graph, _because_ we reject thisglobal constraint-solver approach. Minimizing"error" is meaningless compared to a human _maximizing_ meaning through thoughtful design.
1154
1171
@@ -1166,13 +1183,13 @@ Perhaps programmers ought to put less trust into magic optimizing systems, espec
1166
1183
1167
1184
## Future work
1168
1185
1169
-
We have already integrated iongraph into the Firefox profiler, making it easy for us to view the graphs of the most expensive or impactful functions we find in our performance work. Unfortunately, this is only available in specific builds of the SpiderMonkey shell, and is not available in full browser builds. This is due to architectural differences in how profiling data is captured and the flags with which the browser and shell are built. We would love for Firefox users to someday be able to view these graphs themselves, but at the moment we have no plans to expose this to the browser.
1186
+
We have already integrated iongraph into the Firefox profiler, making it easy for us to view the graphs of the most expensive or impactful functions we find in our performance work. Unfortunately, this is only available in specific builds of the SpiderMonkey shell, and is not available in full browser builds. This is due to architectural differences in how profiling data is captured and the flags with which the browser and shell are built. We would love for Firefox users to someday be able to view these graphs themselves, but at the moment we have no plans to expose this to the browser. However, one bug tracking some related work can be found [here](https://bugzilla.mozilla.org/show_bug.cgi?id=1987005).
1170
1187
1171
1188
In the meantime, however, we plan to continue updating iongraph with more features to assist us in our work. We may in the future update the tool to add richer navigation, search features, and visualization of register allocation info. Ultimately, though, we are likely to work on iongraph sporadically as we need it, with little mind for a product roadmap.
1172
1189
1173
1190
To experiment with iongraph locally, you can run a debug build of the SpiderMonkey shell with `IONFLAGS=logs`; this will dump information to `/tmp/ion.json`. This file can then be loaded into the [standalone deployment of iongraph](https://mozilla-spidermonkey.github.io/iongraph/). Please be aware that the user experience is rough and unpolished in its current state.
1174
1191
1175
-
The source code for iongraph can be found on [GitHub](https://github.com/mozilla-spidermonkey/iongraph).
1192
+
The source code for iongraph can be found on [GitHub](https://github.com/mozilla-spidermonkey/iongraph). If this subject interests you, we would welcome contributions to both the browser and iongraph itself. The best place to reach us is our [Matrix chat](https://chat.mozilla.org/#/room/#spidermonkey:mozilla.org).
1176
1193
1177
1194
<script>
1178
1195
// Terrible code to put code blocks inside HTML tags, because our markdown
0 commit comments