📜 ⬆️ ⬇️

Interprocess messaging performance in node.js

While developing the application on node.js, I faced the need to exchange messages between processes of the same machine. In such a situation, I usually used redis Pub / Sub, with the bonus of being able to scale to multiple servers. But now the question arose about the local exchange and its performance.

I decided to investigate existing messaging options. This task is fairly standard and is known as IPC (Inter Process Communications). But what can be done on js and on what performance at the same time to count?

After conducting a series of tests and getting the results I decided to share them with the habrasoobschestvom. Interested please under the cat.

Options


So, the 1st option, it’s a reference point - redis Pub / Sub . During testing, the redis revealed a fairly decent difference between tcp and unix socket modes. A more productive unix socket was chosen. In the graphs is designated as redis .
')
Further standard api ChildProcess.send and process.on ('message'). This mechanism works using channels (pipes) between the master process and the process started by the node. Thus, the next option is pipe . In the graphs designated as native (pipe) .

The following 2 options are sockets: tcp and unix . In the graphs are labeled as unix socket and tcp .

Methods and test conditions


Initially, I needed to send a message to the central process and get an answer to it. Thus, performance will be further measured in such pairs of in-out messages. Each test script creates 1 master process, and W children (workers). In all tests, the total number of processes is less than the available cores on the test machine.

Each worker starts C asynchronous cycles of sequential sending and waiting for a response of a fixed number of messages - simulating concurrent requests within one process.
In each message, in addition to the field required for the test, an additional paylod line of size P. is added.

Native ChildProcess.send uses JSON to serialize messages. Therefore, tests for unix and tcp sockets were also built using JSON. A test of unix sockets using serialization using gluing and manual string stripping was also added. In the graphs is designated as unix socket opt .

Used node v4.4.5 and redis 3.0.

results


On the X axis, a description of the test of the form WxC, payload = P. For example: 2x4 payload = 100 - 2 workers, each with 4 streams, the size of the additional data of each message is 100 bytes.

payload = 10

payload = 100

payload = 1000

Comments on the results and conclusions


There is practically no performance difference between pipe and unix sockets, tcp is 20-40% slower.

When using only one concurrent stream, redis is flush with tcp, but with increasing competitiveness, the performance does not increase. Perhaps everything rests on 1 common for all processes inbound channel. One way or another, when running the tests, redis consumed up to 50% of the cpu 1 core, so even when trying to optimize for a significant performance increase, it’s impossible to count.

The larger the 1 message, the more justified is the rejection of JSON, but for relatively small messages and loads, the difference is not significant.

By the way, an attempt to use for serialization Buffer showed performance not greater, but sometimes even less than using just strings. Apparently, the Buffer will be justified with predominantly numeric fields in the message.

Total If you do not need to squeeze the maximum performance, built-in ChildProcess.send is enough.

Possible minus - the entire burden falls on the master process, reaching 90% cpu 1 core. Sockets: a more complex implementation, but it is possible to get more performance and take the load on a separate process. Access from other programs is also possible. When using tcp sockets, you can go beyond 1 machine. I suppose that approximately such maximum performance can be squeezed out using ZeroMQ and similar solutions.

Source codes of tests are available here .

Source: https://habr.com/ru/post/315200/


All Articles