Whiteboard Visualizations
FizzBee generates multiple visualizations and diagrams. So far you would have seen, automatically generated state diagrams. In addition to state diagrams, FizzBee also generates sequence diagrams and algorithm visualizations.
These are helpful in understanding the algorithm and the system behavior.
Feature | Description |
---|---|
Pseudo Code to Visualizations | Generates sequence, state, and algorithm diagrams directly from high-level, Python-like pseudo code. |
Zero Extra Effort | Visualizations are created directly from your pseudo code with no additional manual input required. |
Interactive Experience | Provides a dynamic, whiteboard-like interface to explore states, transitions, and scenarios in real time. |
Comprehensive Simulation | Automatically simulates complex scenarios like non-atomic operations, crashes, message loss, concurrency, and visualizes all possible states. |
Correctness Assertion | Enables adding assertions to ensure the design meets safety and liveness requirements. |
Easy to Use | Familiar Python-like syntax reduces the learning curve compared to other formal methods tools. |
On the fizzbee playground, you can enable the whiteboard visualizations by setting
the Enable Whiteboard
checkbox. Then click Run
button.
Once the model checking is done, you can see a link to the Explorer
in the Console
.
Clicking on the Explorer
link will open the explorer in a new tab.
Before we go over the tutorial, let’s see a complete working example.
- Open the Two Phase Commit example in the play ground
- Enable
Enable Whiteboard
checkbox, and Run. - Once the model checker completes, click on
Communication Diagram
link in the console. This will show the block diagram for the two phase commit protocol.
- Click on the
Explorer
link in the console. - You would see the Init state of the system
- On the left, you will see various buttons for the actions. Click on the
Coordinator#0.Write
button. it should start the sequence diagram. Continue to click on the buttons to see the sequence diagram. If you always choose the success path, you will see eventually both the participants and the coordinator reach thecommitted
state.sequenceDiagram note left of 'Coordinator#0': Write 'Coordinator#0' ->> 'Participant#0': Prepare() 'Participant#0' -->> 'Coordinator#0': ("prepared") 'Coordinator#0' ->> 'Participant#1': Prepare() 'Participant#1' -->> 'Coordinator#0': ("prepared") 'Coordinator#0' ->> 'Participant#0': Commit() 'Participant#0' -->> 'Coordinator#0': . 'Coordinator#0' ->> 'Participant#1': Commit() 'Participant#1' -->> 'Coordinator#0': .
- Play around with the explorer to see what happens when a participant aborted.
sequenceDiagram note left of 'Coordinator#0': Write 'Coordinator#0' ->> 'Participant#0': Prepare() 'Participant#0' -->> 'Coordinator#0': ("prepared") 'Coordinator#0' ->> 'Participant#1': Prepare() 'Participant#1' -->> 'Coordinator#0': ("aborted") 'Coordinator#0' ->> 'Participant#0': Abort() 'Participant#0' -->> 'Coordinator#0': . 'Coordinator#0' ->> 'Participant#1': Abort() 'Participant#1' -->> 'Coordinator#0': .
- You can explorer most possible sequences and states.
Let’s try another visualization - the Insertion Sort algorithm. FizzBee is a formal verification language, so verifying Insertion Sort is not the best use case. But this introduces the visualization capabilities.
If you look at the insertion_sort method, the code is actually a working python code (with only the method definition syntax being different)
Checkpoint is similar to breakpoint in debugger, but this is not running the code during exploration instead it executes the model and checkpoints the state at various points.
There are default checkpoints at the start of each action, any non-determinism or when there are any yields.
You can set explicit checkpoints using `checkpoint`
.
|
|
- Run the above code in the playground with
Enable Whiteboard
checked. - Click on the
Explorer
link in the console - Play around by clicking the buttons. It will only show the states, there are no sequence diagrams for this example. (Sequence diagrams are only generated when there are roles)
- While the states are shown, with
cur
andins
variable, it would be nicer to show them as pointers to the position in the array. This information is not available in the spec so far. So this should be added as an additional config.
- On the left-bottom, you will see the
Config
text area. Insert the following code.variables: cur: index_of: arr ins: index_of: arr
- Click on buttons to see the states change as the algorithm progresses.
FizzBee is not a usual visualization tool, it is a design specification system. You can model your design in an python-like language and use that to validate the design to check for issues like concurrency, consistency, fault tolerance, then model performance like error ratio, tail latency distribution and more.
As a design specification, FizzBee generates various visualizations to help you understand the system behavior that can be shard with your team. This makes it easier to explain the design for your team to review, saving significant amount of time.
For more details on the language, refer to the FizzBee Language Reference.
In the document, we will do a quick overview of the language necessary to generate the visualizations and skip the model checking parts.
FizzBee uses a variant of Python syntax, and for the most part relies on Starlark for evaluating expressions.
So all the standard Python datatypes like int
, float
, str
, list
, dict
etc are supported.
|
|
The top section is the frontmatter, where you can set various model checking options.
In this example, our spec just initializes the variables, and there are no action after that. So effectively, this implies the system cannot progress after the Init, so it is considered a deadlock For this example, we are just suppressing this error.
Run this example with the whiteboard enabled, then click on the Explorer
link in the console.
You should see something like,
Actions are the basic building blocks of the system. They can either represent steps triggered by the user or the components that are external to the system being modelled.
|
|
Open the playground, and try the whiteboard. This time you will see, the elements
list
that is initially empty. On the left, click on the Produce
button,
then pick an element to add to the list.
you will see the elements
getting updated. Once an element is added, you would see
two actions Produce
and Consume
available (as shown in the image below). Click on Consume
to remove the element.
Try Produce multiple times to fill to capacity, then you will see Produce action is not enabled anymore.
This should explain how require
and any
keywords work
We saw how to display the datastructure. Many times, we would want to see how the data access. Since the index information is not preserved, we need to add a bit of extra configuration.
|
|
I will show the block diagram like this.
Now, to specify the cursor variable points to the index of the elements array,
On the left bottom text area, set
variables:
cursor:
index_of: elements
Now, click the MoveCursor buttons. You will see a diagram like this.
In the above example, we saw how each action is a step in the system. Let us try slightly more complex example where we have a loop. This is a simple example of summing the elements in the array.
|
|
One action Sum
sums the results, and the next action Restart
resets the sum and cursor.
If you run this, you will see the sum being calculated. But you will not see the intermediate steps.
The states graph will show,
To see the intermediate steps, we can add a checkpoint in the loop.
*** 7,12 ****
--- 7,13 ----
atomic action Sum:
require sum == 0
for i in range(0, len(elements)):
+ `checkpoint`
cursor = i
sum += elements[i]
Run and open the states graph, you will see a lot more intermediate steps.
Then, open the explorer. Similar to previous example, set the cursor.
variables:
cursor:
index_of: elements
Now, click the Sum button and play.
To role more about roles, see Roles
Let us take a simple message passing example.
|
|
Once you run with the whiteboard enabled, open the explorer, and click Process
button, you will see the sequence diagram.
sequenceDiagram note left of 'Sender#0': Process 'Sender#0' ->> 'Receiver#0': Greet(name: "Alice") 'Receiver#0' -->> 'Sender#0': ("Hello Alice")
As a trivial example, there is only one action and none of these have any states. Since there are no states, the system does not explore what happens if receiver is not available or if the message is lost, or the receiver processed it, but the response was lost and so on.
Example: State updates with message passing
|
|
When you run it, and open the explorer, you will see the states of the caller and server. Obviously,
- Both the caller and server are in the
init
state. - When you click on the
Send
button, the caller changes tocalling
, and server changes toinit
state. - At the point, wo possible things can happen.
i. Happy case: Continue by clicking
thread-0
. The server changes todone
state. You’ll also see a sequence diagram. ii. Error case: Error case: Click oncrash
. This path implies, either the caller crashed before sending or server crashed before the server processed the request. So the caller will continue to think it is in calling state. - You can similarly try crash after the server processed the request, and see the server in
done
state and caller incalling
state. - Finally, you can try crash after the caller received the response, and see the caller in
done
state and server indone
state.
An example state where the caller is in calling
state and server is in done
state is shown below.
sequenceDiagram note left of 'Caller#0': Send 'Caller#0' ->> 'Server#0': Process() 'Server#0' -->> 'Caller#0': . 'Caller#0'->>'Caller#0': crash
Now, go back to the first example with two-phase commit and try to understand the behavior.
FizzBee is a powerful tool to model and visualize the system behavior. In addition to checking for correctness, it can also be used to generate visualizations that can be shared with the team to explain the design.
The best of all, unlike any other formal verification system, FizzBee uses python’ish language making it easy to ramp up on day 1.
In other visualization tools, you will have to manually create the sequences. Most likely, you won’t be able to create the sequences for all the important paths. But with FizzBee, you can explore all possible paths. Also, by describing your system design in a precise language, it doubles as a system specification language replacing significant portions of the design document.