|
| 1 | +.. title: Some Ways that PyPy uses Graphviz |
| 2 | +.. slug: ways-pypy-graphviz |
| 3 | +.. date: 2021-04-26 16:00:00 UTC |
| 4 | +.. tags: |
| 5 | +.. category: |
| 6 | +.. link: |
| 7 | +.. description: |
| 8 | +.. type: rest |
| 9 | +.. author: Carl Friedrich Bolz-Tereick |
| 10 | + |
| 11 | +================================ |
| 12 | +Some way that PyPy uses Graphviz |
| 13 | +================================ |
| 14 | + |
| 15 | +Somebody wrote this super cool thread on Twitter about using Graphviz_ to make |
| 16 | +software visualize its internal state: |
| 17 | + |
| 18 | +.. _Graphviz: https://graphviz.org |
| 19 | + |
| 20 | +.. raw:: html |
| 21 | + |
| 22 | + <blockquote class="twitter-tweet"><p lang="en" dir="ltr">🧵 Make yours and everybody else's lives slightly less terrible by having all your programs print out their internal stuff as pictures; ✨ a thread ✨ <a href="https://t.co/NjQ42bXN2E">pic.twitter.com/NjQ42bXN2E</a></p>— Kate (@thingskatedid) <a href="https://twitter.com/thingskatedid/status/1386077306381242371?ref_src=twsrc%5Etfw">April 24, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> |
| 23 | + |
| 24 | +PyPy is using this approach a lot too and I collected a few screenshots of that |
| 25 | +technique `on Twitter`_ and I thought it would make a nice blog post too! |
| 26 | + |
| 27 | +.. _`on Twitter`: https://twitter.com/cfbolz/status/1386315196982079491 |
| 28 | + |
| 29 | + |
| 30 | +The most important view early in the project, and the way that our Graphviz |
| 31 | +visualizations got started was that we implemented a way to look at the control |
| 32 | +flow graphs of our RPython functions after type inference. They are in static |
| 33 | +single information form (SSI_), a variant of SSA_ form. Hovering over the |
| 34 | +variables shows the inferred types in the footer: |
| 35 | + |
| 36 | +.. _SSI: https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.1.9976 |
| 37 | +.. _SSA: https://en.wikipedia.org/wiki/Static_single_assignment_form |
| 38 | + |
| 39 | +.. image:: /images/2021-graphviz-02-cfg-types.png |
| 40 | + |
| 41 | +There's another view that shows the inferred call graph of the program: |
| 42 | + |
| 43 | +.. image:: /images/2021-graphviz-05-call-graph.png |
| 44 | + |
| 45 | +A related viewer shows the inferred class hierarchy (in this case the exception |
| 46 | +hierarchy) and you can focus on a single class, which will show you its base |
| 47 | +classes and all the methods and instance attributes that were found: |
| 48 | + |
| 49 | +.. image:: /images/2021-graphviz-03-classhier.png |
| 50 | + |
| 51 | +.. image:: /images/2021-graphviz-04-classhier-detailed.png |
| 52 | + |
| 53 | +We also have a view to show us the traces that are produced by the tracing JIT |
| 54 | +tests. this viewer doesn't really scale to the big traces that the full Python |
| 55 | +interpreter produces, but it's really useful during testing: |
| 56 | + |
| 57 | +.. image:: /images/2021-graphviz-06-trace.png |
| 58 | + |
| 59 | +Then there are more traditional tree views, eg here is a parse tree for a small |
| 60 | +piece of Python source code: |
| 61 | + |
| 62 | +.. image:: /images/2021-graphviz-07-parse-tree.png |
| 63 | + |
| 64 | +Parsing-related we have visualized the `DFAs of the parser`_ in the past, |
| 65 | +though the code is unfortunately lost. |
| 66 | + |
| 67 | +.. _`DFAs of the parser`: https://www.pypy.org/posts/2008/01/visualizing-python-tokenizer-5020282079473796926.html |
| 68 | + |
| 69 | +All these visualizations are made by walking the relevant data structures and |
| 70 | +producing a Graphviz input file using a bit of string manipulation, which is |
| 71 | +quite easy to do. Knowing a bit of Graphviz is a really useful skill, it's |
| 72 | +super easy to make throwaway visualizations. |
| 73 | + |
| 74 | +For example here is a one-off thing I did when debugging our `JSON parser`_ to |
| 75 | +show the properties of the objects used in a huge example json file: |
| 76 | + |
| 77 | +.. image:: /images/2021-graphviz-08-json-parser.png |
| 78 | + |
| 79 | +.. _`JSON parser`: https://morepypy.blogspot.com/2019/10/pypys-new-json-parser.html |
| 80 | + |
| 81 | +On top of graphviz, we have a custom tool called the dotviewer_, which is |
| 82 | +written in Python and uses Pygame_ to give you a zoomable, pannable, searchable |
| 83 | +way to look at huge Graphviz graphs. All the images in this post are |
| 84 | +screenshots of that tool. In its simplest form it takes any .dot files as |
| 85 | +input. |
| 86 | + |
| 87 | +.. _dotviewer: https://foss.heptapod.net/pypy/pypy/-/tree/branch/default/dotviewer |
| 88 | + |
| 89 | +.. _Pygame: https://pygame.org |
| 90 | + |
| 91 | +Here's a small video dotviewer, moving around and searching in the json graph. |
| 92 | +By writing a bit of extra Python code the dotviewer can also be extended to add |
| 93 | +hyperlinks in the graphs to navigate to different views (for example, we did |
| 94 | +that for the callgraphs above). |
| 95 | + |
| 96 | +.. raw:: html |
| 97 | + |
| 98 | + <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/SsTmJ5_Yzh8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> |
| 99 | + |
| 100 | + |
| 101 | +All in all this is a really powerful approach to understand the behaviour of |
| 102 | +some of code, or when debugging complicated problems and we have gotten a |
| 103 | +huge amount of milage out of this over the years. It can be seen as an instance |
| 104 | +of `moldable development`_ ("a way of programming through which you construct |
| 105 | +custom tools for each problem"). And it's really easy to get into! The Graphviz |
| 106 | +language is quite a simple text-based language that can be applied to a huge |
| 107 | +amount of different visualization situations. |
| 108 | + |
| 109 | +.. _`moldable development`: https://moldabledevelopment.com/ |
| 110 | + |
0 commit comments