I won’t dive deeper into the telecommunications aspect. By now you should already feel the importance of real-time data (visualization).

The main functionality looked like this:

Demo: Part of the application I developed for the SUNSEED project.

Main app functionality: Distribution system operators could select different SE (State Estimation) and PMU (Phasor Measurement Unit) streams and see the incoming data in real time.

The mini-catch was that the frequency of these streams was ≈50 Hz (50 messages/second).

“So how do you effectively render 50 data points per second (or more) in a line chart using JavaScript?” …

The common way to render real-time charts using JavaScript libraries

The first thing that came to mind was to explore the web and books to find out if similar high-frequency problems had already been tackled with JavaScript. Sadly (or thankfully), nothing fruitful came up. That forced me to explore a little byte more :)

In the following examples I’m using Rickshaw.js SVG charting library that is based on D3.js.

If you have ever scouted the web regarding real-time charts with JavaScript libraries, you probably found examples similar to this:

Real-time chart with 1s update interval using Rickshaw.js.

Yeah, a 1000 ms update interval. Works fine.

No problem, let’s modify the updateInterval variable to 20 (to simulate a 50 Hz stream), it should work!

Real-time chart with 20 ms update interval using Rickshaw.js.

If you’re on a modern machine, chances are that everything seems to work fairly smooth. Fire up your task manager and take a glimpse at the CPU usage. Now try the same approach with multiple multi-series line charts and watch carefully the CPU usage of your app …

Let’s take a second and think about what is happening beneath the facade.

…

THE CHART IS RENDERING EVERY ≈20 ms i.e. ≈50x per second!

This clearly causes a performance issue. So how can we tackle this? Inventiveness to the rescue!

Optimization

In order to reduce the CPU load, we must lower the frequency of the chart render function executions.

The magic idea:

What if we try to render the chart only after N data points have already been inserted (but not yet re-rendered)?

Theoretically, if streamFrequency=50 Hz and N=5, this means that the chart render function is called 10x in a second → every ≈100 ms.

Let’s try this!

Optimized real-time chart with 20 ms update interval using Rickshaw.js. with N=5.

The result:

(+) If we compare CPU usage before and after, we can see that the CPU is far less under load.

(-) The trade-off is that the refresh-rate is 10Hz on average, which makes the visualization seem a little less smooth. This effect is minimized when the incoming values of the visualized data stream are similar to each other OR if the Y-axis’s min-max interval is larger.

Try it out yourself!

I prepared 2 GitHub repos server and client for you to try it out!

To make the application as real-world-like as possible, we will set up a simple MQTT broker that listens on port 1883 using Moquette. This will simulate a real-world IoT data stream. The server-side will publish and subscribe to topics on this MQTT broker in order to send and receive data. After the server receives messages from a MQTT topic, it will forward them to the client using Socket.io.

Installation:

Prerequisites

Be sure you have these downloaded/installed on your machine:

node.js

npm

Moquette (MQTT broker) (or any other MQTT broker that listens on port 1883)

If using Moquette, be sure to have Java JDK installed (tested with JDK 8). Didn’t work with JDK9 and JDK10 on my machine.

Installing & running

You will need 3 terminal instances for running this project.

1. Moquette:

download Moquette (under “1 minute set up” click on BinTray link)

link) open Terminal1

run:

cd bin

./moquette.sh (If you’re on Windows, run the last command as):

.\moquette.bat

2. Server

download mqtt-realtime-chart-server

open Terminal2

unpack and run inside root folder:

npm install

npm start

3. Client

download mqtt-realtime-chart-client

open Terminal3

unpack and run inside root folder:

npm install

npm start

After the client is compiled, you will see the link in the terminal (e.g. http://localhost:8080) where the application is currently running. Use your browser to navigate to that link.

If everything went smoothly, you should see a real-time chart with data frequency of around 50 Hz! You can now explore the discussed optimization technique by changing the slider value. Don’t forget to have an eye on the CPU usage in the task manager while doing so.