Many applications in gateways acquire data from sensors, work on that data and then forward that data to a backend. To get some idea about the performance of such applications, we were curious about the following questions:
- How many messages per second can we send from a gateway to a backend?
- How does a solution built in Reactive Blocks compare with one in pure Java?
- How can we use multiple cores in a processors and receive, process and send data simultaneously?
As reference hardware, we use a Raspberry Pi 2 (Model B) with a quad-core Broadcom BCM 2836 CPU at 900 MHz with 1GB RAM.
Sending Messages from the Gateway to the Backend
For the protocol to send messages to the backend, we chose MQTT. We have our own MQTT server running on Amazon AWS, in the Ireland data center. And our gateway is located in Trondheim, Norway, so that signals had to cross the North Sea.
The setup for the test application looks like this:
We send messages in bulks of 1, 2, 5, … 10 000, and measure the time how long it takes until they are sent.
First of all, the experiment illustrates how significant the difference between qos=0 and qos=2 is. In MQTT it is possible to set the quality of service (qos) for a message. With qos=0, messages are not acknowledged and there are no guarantees. With qos=2, the message reception is guaranteed and there are no duplicates. With our setup, it was possible to send on average 8 to 9 messages per second with qos=2, that means acknowledged messages. With qos=0, the average is 1000 messages per second, so more than a hundred times more! Of course, this is not surprising, because in the latter the messages are just sent out and the sender does not wait for acknowledgments from the server. Therefore, it really makes sense to decide which qos level an application needs.
Pure Java and Reactive Blocks
We also checked how the pure Java solution (using Paho) compares to the Reactive Blocks solution. Reactive Blocks uses in its core also Paho, but encapsulated in the Blocks and with automatically generated code. Here are the results:
The time needed to publish a given number of MQTT messages using the a Java only application compared to the Java code generated by Reactive Blocks is very much the same. That means that the generated code is as efficient as the programmed code.
Using the Multi-Core
The Raspberry Pi 2 comes with a quad-core CPU making it possible to process tasks in parallel. This is handy for gateway applications were typically sensor data has to be received, some processing has to be done and data has to be published. We have tested this typical use case by simulating sensor data within one thread, doing some hard polynomial calculation for each sensor value within another thread and publishing data via MQTT within another thread.
By dividing these tasks to different threads, they can be processed in parallel by the four cores of the Raspberry Pi. Here we have chosen to produce around 18000 sensor events per seconds. Block Polynomial Calculation solves a polynomial equation for each incoming event, emitting an average value for each 2000 incoming events. This average value is then published via block MQTT Publish. In other words, there will around 9 MQTT messages to publish with QoS 2 each second. Block Buffer Eager Simple from our Buffer library stores the produced messages to provide them whenever block MQTT Publish reports the preceding message to be published.
Dividing this kind of application to different cores is of course possible by programming Java only. However Reactive Blocks makes synchronization of the involved threads much easier resulting in robust and reliable applications.