Slow WebSockets

Client - server architecture is a popular answer for multi-user, remote applications. Comparing with single-user programs working on local machine, this architecture always has worse responsiveness. Today's world of multiuser, remote application is dominated by web technology. When starting a new project one could think "Wouldn't it be better to choose the WebSocket protocol to speed up client - server communication?". This document presents the results of tests, that have been performed to check if sending data through WebSocket is faster then over HTTP and if there is performance profit of establising connection only once for a user session.

Tests specification

Testing scenario was comparing effectiveness of sending various amount of data through HTTP and WebSocket RFC 6455.

The tests were executed in four environments:

  • WAN 10 Gb,
  • LAN - WiFi,
  • HSDPA+,
  • Localhost,

Each test was run twice in each environment and then a better result was chosen.

Software:

Test cases:

  • 1 char, repeats: 100 times
  • 0.5 kB, repeats: 10 times
  • 1 kB, repeats: 10 times
  • 100 kB, repeats: 10 times
  • 1 MB, repeats: 1 times
  • 10 MB, repeats: 1 times

Y-axis presents time in seconds. The smaller, the better.

../../static/art/1-slow-websocekts/wan.png ../../static/art/1-slow-websocekts/lan.png ../../static/art/1-slow-websocekts/hsdpa.png

Looking at the charts from the Internet application point of view (WAN and HSDPA+), WebSocket transmission is faster than HTTP but only for data smaller then 100 KB. Considering Intranet application (LAN) we can see, that only sending one char was noticebly faster in WebSocekt technology.

Let's look how is it doing, when sending larger package of data, 10 MB:

../../static/art/1-slow-websocekts/wan10.png ../../static/art/1-slow-websocekts/lan10.png ../../static/art/1-slow-websocekts/hsdpa10.png

In all cases sending 10 MB data via websocket is extremely ineffective.

More information about effectiveness of protocols can be given by the localhost test, in which network delays are eliminated.

../../static/art/1-slow-websocekts/lo.png ../../static/art/1-slow-websocekts/lo10.png

Investigation

The localhost chart gave us a cue, that the problem probably lies in websocket protocol itself.

In such a case, let's examine the sending function:

Profiling websocekt-client send() function:

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.000    0.000    4.550    4.550 <string>:1(<module>)
     1    0.000    0.000    0.000    0.000 websocket.py:256(__init__)
     1    0.000    0.000    0.000    0.000 websocket.py:276(create_frame)
     1    0.011    0.011    4.512    4.512 websocket.py:292(format)
     5    0.000    0.000    0.000    0.000 websocket.py:296(<genexpr>)
     1    0.009    0.009    4.500    4.500 websocket.py:323(_get_masked)
     1    4.480    4.480    4.491    4.491 websocket.py:327(mask)           (!)
     1    0.011    0.011    4.550    4.550 websocket.py:549(send)
     1    0.000    0.000    0.027    0.027 websocket.py:728(_send)
     1    0.000    0.000    0.000    0.000 {built-in method any}
     1    0.000    0.000    4.550    4.550 {built-in method exec}
     2    0.000    0.000    0.000    0.000 {built-in method isinstance}
     3    0.000    0.000    0.000    0.000 {built-in method len}
     1    0.000    0.000    0.000    0.000 {built-in method pack}
     1    0.000    0.000    0.000    0.000 {built-in method urandom}
     1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
     1    0.027    0.027    0.027    0.027 {method 'send' of '_socket.socket' objects}
     1    0.010    0.010    0.010    0.010 {method 'tobytes' of 'array.array' objects}

According to the Websocket protocol RFC 6455 : ..

6.1 5. If the data is being sent by the client, the frame(s) MUST be masked as defined in Section 5.3.

This is done to prevent cache poisoning on proxy.

Conclusion

Taking aside profits of bidirectional communication, WebSocket could be a good solution for Internet application, where clients send small data, very often to the server. For sending larger data it would be good idea to create dedicated, non-WebSocket channel.

For Intranet application, it would be probably better to stay with HTTP technology. Architecture would be easier, limited only to one channel.