Skip to content

Lab note

Ubigraph server and graph streaming

The Ubigraph viewer accepts changes one at a time. That single decision is what makes the animation demo possible and what shapes the rest of the API.

A diagram showing a client streaming small changes into a viewer

The streaming model in one sentence

The viewer holds the graph, the client sends small changes, and the picture stays continuous through any amount of change.

That sentence is the whole model. The rest of this note is about why it works.

What “one change at a time” buys you

A graph viewer has two reasonable choices for how to accept input. It can ask the client for the whole graph every time anything changes, or it can ask the client for the change.

The whole-graph model is simpler to build. It is harder to live with. Every change forces the viewer to re-think the layout from scratch. The picture flickers. The reader loses the thread. The viewer cannot animate anything because there is no continuity between frames.

The per-change model is harder to build. It buys you several things at once:

  • The viewer keeps the previous layout as a starting point. A small change produces a small visual response.
  • The viewer can run the layout continuously. New changes feed into a layout that is already in motion.
  • The client can produce changes at whatever rate makes sense for the program, not at the viewer’s frame rate.
  • The viewer can drop changes under load and the picture stays sensible, just slightly behind.

Ubigraph commits to the per-change model. The animation demo is the visible payoff.

What this means for the client

A client built for a streaming viewer looks different from one built for a whole-graph viewer.

  • The client does not keep a copy of the graph that it re-sends every step. It keeps the ids of the vertices and edges it has created, and that is enough.
  • The client does not have to think about frame rate. It can produce changes when changes happen.
  • The client does not have a “render” call. Rendering is the viewer’s continuous job.

The change is not just stylistic. It changes the kind of program a client wants to be. A whole-graph client tends to look like a renderer. A streaming client tends to look like a simulation.

How the server side stays sane

The viewer has to handle a stream of changes without falling behind. There are two design choices that make this practical.

First, the layout runs as a continuous physical simulation rather than as a render pipeline. The layout is always in motion. New changes do not interrupt a render - they perturb the simulation. The picture you see is the current state of the simulation, drawn at whatever frame rate the renderer can manage.

Second, the viewer can drop ahead of the simulation under load. If changes are coming in faster than the layout can settle, the viewer is still drawing something useful. The picture is approximate but continuous. A whole-graph viewer would block. A streaming viewer degrades.

Both choices are independent of XML-RPC, of Ubigraph, and of any specific implementation. They are the shape of the problem.

Translating to current tooling

A current setup that wants the same behaviour does not need to be a clone of the original viewer. The pattern is reproducible over any small RPC mechanism.

A minimal translation:

  • Pick a graph viewer with a streaming API or a small enough one that you can wrap it. Force-directed viewers are the natural fit because they already run a continuous simulation.
  • Expose create_vertex, create_edge, remove_vertex, remove_edge, set_attribute, and clear over your RPC of choice.
  • Write a small client that produces changes as the program runs.
  • Let the viewer do its own rendering. Do not tell it when to redraw.

The graph visualisation alternatives note goes into specific tooling for the viewer side. The XML-RPC graph control note covers the client side.

A common failure mode

The most common mistake when porting an Ubigraph-style example to a different viewer is to treat the viewer as a renderer.

You see this in code that builds the whole graph in memory, sends it to the viewer in a single call, and then re-sends it every time anything changes. The animation demo will look terrible in that setup because the viewer is being asked to start over on every change.

The fix is small. Build the graph incrementally. Send changes as they happen. Stop sending the whole graph.

If you find yourself looking at flickery animation in a port, this is almost certainly the cause.

Where this connects in the rest of the site