Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

.nornir/graph-for-idiots.md

The graph subsystem — for idiots

Class: idiot. Every step, nothing assumed. Goal: draw a graph on screen and prove it drew, from a cold shell. If you already know Rust, read graph-guide.md instead — this one spells out every keystroke. (Folds the old facett-graphview-for-dummies.md — same plain-English content, now covering all five graph crates.)

What you need first

cd /run/media/rickard/T9/git/facett

What "the graph subsystem" even is

You found five crates that all do one thing: draw boxes with lines between them (a dependency graph, a pipeline, a graph database, a 3D call graph, a map of a few servers) — and keep drawing them fast even when there are a lot of boxes. No graph-theory or GPU knowledge needed to use any of them.

crate draws…
facett-graph a simple graph, or a left-to-right dependency chart
facett-graphview the same thing, but built to stay fast at huge sizes, and it can hand you back raw pixels
facett-graphpan a graph you can drag around and zoom into
facett-graph3d a graph floating in 3D that spins
facett-syschart a handful of boxes (services) with counters on them, click one to see detail

The one big idea in facett-graphview: it picks GPU or CPU by itself

Drawing a huge graph is expensive. A graphics card (GPU) does it fast, but not every machine has a usable one (a CI server, a headless box, a laptop with a flaky driver). So facett-graphview doesn't demand a GPU. It probes the machine and picks:

GraphModel + Decorations → decide(probe) → Backend{vello GPU | vello_cpu SIMD} → RGBA pixels

Step 1 — build it

Type and press Enter:

cargo build -p facett-graph -p facett-graphview -p facett-graphpan -p facett-graph3d -p facett-syschart

Wait for it to finish with no red text.

Step 2 — run the tests (proof it draws, no window needed)

Type and press Enter:

cargo test -p facett-graph -p facett-graphview -p facett-graphpan -p facett-graph3d -p facett-syschart

Green test result: ok lines for each crate = every one of them can build a graph, paint it, and check what got painted — without opening a window. That "headless" trick is explained in elm-for-idiots.md if you want to know how.

Step 3 — make one crate actually spit out a picture

facett-graphview ships an example that renders a graph straight to a PNG file on disk — the easiest way to see something without wiring up a whole app. Type and press Enter:

cargo run -p facett-graphview --example render_png

Look at the terminal output for the file path it wrote, then open that .png in any image viewer. You should see coloured boxes joined by lines.

Step 4 — turn on the GPU path (optional)

By default everything above used the CPU. To also compile the GPU seam:

cargo build -p facett-graphview --features gpu

This does not change what you see yet (both paths currently draw through the same CPU rasterizer under the hood — that's an intentional, documented in-progress state, not a bug) — it proves the GPU wiring compiles.

Step 5 — pick a node and click it (interactive canvas)

If you're wiring one of these into a live app (not required to just try it out), the "click a node, see it light up" behaviour lives in DecoratedGraphView (facett-graphview), GraphPanView (facett-graphpan), DepGraphView (facett-graph), Graph3D (facett-graph3d), and SystemChart (facett-syschart). Every one of them follows the exact same recipe:

  1. You give it nodes + edges (plain data: an id, a label, a colour, a position).
  2. It paints them and watches for clicks/drags/scrolls.
  3. A click on a node doesn't change anything by itself — it becomes a named Msg (like Select("a")), and a single update function applies it.
  4. You can replay that exact same Msg in a test with no window at all and check the result — see elm-for-idiots.md steps 5-8 for the full walkthrough of writing that kind of test.

Step 5b — "I already know where my nodes go"

The 3-D one (Graph3D) normally decides where each node goes for you: on a sphere, on a spiral, on a cube grid, or by letting a physics relaxation push them apart. That is the right answer when the nodes are just things. It is the wrong answer when they are places with a number attached — road sensors on a map, each with a speed; servers on a floor plan, each with a load.

For that, you place them yourself:

use facett_graph3d::{Graph3D, Layout3D};

// One [x, y, z] per node, same order as the nodes, all numbers roughly -1..1.
// x and y = where it is on your map. z (up) = the number you measured.
let g = Graph3D::new(nodes, edges, Layout3D::Given).with_positions(positions);

Three things worth knowing, in plain words:

You can see it running: start the demo (Step 3) and open the tab called graph3d-given. It is a little city of traffic sensors — flat on the map, high where traffic is fast, sunk in the middle where it is jammed.

Step 6 — "is facett-graphview finished?"

No — it's a foundation spike. What works today: the model, the CPU rasterizer (proven, tested), and the GPU code path compiles (the version-matched vello/wgpu/egui-wgpu seam). What's not done yet: reading the finished picture back off the GPU as a live framebuffer, plus turning on the "handle a huge graph" tools it already ships (only-draw-what's-on-screen culling; the edge-bundling, community/semantic-zoom, and GPU-layout modules exist and are tested standalone, but a host has to call them explicitly — they aren't wired into the default render path yet), and the adapters that turn a nornir dep graph / a FalkorDB graph / a pipeline straight into a GraphModel.

Step 7 — "so how fast is it?"

There's a benchmark (cargo bench -p facett-graphview), but be honest about it: right now both backends actually draw on the CPU (the GPU readback is a follow-up), so the number is a CPU-path baseline, not a "we beat Graphviz on the GPU" claim. Don't quote it that way yet.

Step 8 — save your work (if you changed something)

Type these three, pressing Enter after each:

git add -A
git commit -m "facett-graph*: <what you changed>"
git push

That's the whole tour. For the exact API of each crate, read graph-guide.md; for why it's built this way, graph-reasoning.md.