A few benchmark tests of network frameworks

Hi Habr! A couple of months ago, I wanted to test the performance of some network frameworks in order to understand how big the gap between them is. Do I need to use Node.js where I would like Python with Gevent or need Ruby with its EventMachine. I want to draw your attention to the fact that these materials are not a guide to choosing a framework and may contain contentious points. I was not going to publish the results of this study at all, but when they caught my eye I caught myself thinking that this could be useful to someone. Now I will start to shower you with graphs.

image



1. Text / Httperf / VPS 1 CPU, 512Mb RAM


The first test I conducted on the cheapest VPS DigitalOcean (1 Core, 512Mb RAM, 20Gb SSD). For performance testing, the httperf utility was used . In order to produce the necessary load, VPS of the same configuration were involved, in the amount of 5 pieces. To run the test on all clients at the same time, I used the autobench utility with the following parameters:

autobench_admin --single_host --host1 example.com --port1 8080 --uri1 / --low_rate 50 --high_rate 600 --rate_step 10 --num_call 10 --num_conn 6000 --timeout 5 --clients XX.XX.XX.XX:4600,XX.XX.XX.XX:4600,XX.XX.XX.XX:4600,XX.XX.XX.XX:4600,XX.XX.XX.XX:4600 --file bench.tsv

This test starts at 50 connections per second (10 requests through one connection) and reaches 600 connections in 10 connections per second. Each test establishes a total of 6000 connections and all requests that were not processed within 5 seconds are considered an error.

All HTTP servers do the same thing, namely they return the string “I am a stupid HTTP server!” For each request. The results were as follows ( along the X axis - the number of requests per second ):

CPU load



RAM consumption (% of 512Mb)



Number of replies



Response Time (in milliseconds)



Number of mistakes



As soon as we reach 100% CPU utilization, RAM consumption begins to increase, the number of responses drops, the response time for each request grows and errors begin to appear. As I wrote above, each request that did not receive a response within 5 seconds is considered an error, and this is exactly what happens here, this can be traced on the “Response Time” graph.

Results (in brackets the number of processed requests without errors):

  1. Gevent ( 4700 )
  2. Express.js ( 3600 )
  3. Eventlet ( 3200 )
  4. Tornado ( 2200 )

I am never completely satisfied with my work, so after a couple of hours I decided that testing performance on VPS was not the best choice. Between the frameworks, the difference in performance is understandable and some conclusions can be drawn, but we can’t find out how many clients we can service on the same core of a real processor. It is one thing to share unknown resources with someone and quite another when all the resources are known and at our disposal.

2.Text / Httperf / Intel Core i7-4770 Quad-Core Haswell, 32 GB DDR3 RAM


For the next test, I rented a dedicated server from Hetzner (EX40) with an Intel Core i7-4770 Quad-Core Haswell processor and 32 GB DDR3 RAM.

This time, I created 10 VPS that will create the necessary load and launched autobench with the following parameters:

autobench_admin --single_host --host1 example.com --port1 8080 --uri1 / --low_rate 50 --high_rate 1500 --rate_step 50 --num_call 10 --num_conn 15000 --timeout 5 --clients XX.XX.XX.XX:4600,XX.XX.XX.XX:4600,XX.XX.XX.XX:4600,XX.XX.XX.XX:4600,XX.XX.XX.XX:4600 ... --file bench.tsv

This test starts execution with 50 connections per second (10 requests through one connection) and with a step of 50 connections per second reaches 1500. Each test sets only 15,000 connections and all requests that were not processed within 5 seconds are considered an error.

The source code of the servers is the same as in the first test. One copy of the server has been launched, which uses only 1 core. I added Twisted 13.2 and Eventmachine frameworks to this test .1.0.3. I deleted the memory consumption from the test results because the difference, by modern standards, is negligible. I will not pull the cat by the tail, here are the results:

CPU load




Number of replies




Response Time (in milliseconds)




Number of mistakes




Here, as before, they ran into the CPU, which was to be expected. On average, productivity here is 3 times higher than on VPS DigitalOcean (1 Core, 512Mb), from which we can draw the appropriate conclusions about the amount of resources allocated to us.

Results (in brackets the number of processed requests without errors):

  1. Eventmachine ( details below )
  2. Gevent ( 12500 )
  3. Express.js ( 11500 )
  4. Eventlet ( 9000 )
  5. Twisted ( 7000 )
  6. Tornado ( 6500 )

Eventmachine


Eventmachine surprised me with its performance and went far from competitors, because of which I had to increase the load to 25,000 requests per second specifically for him. The result on the graphs:

CPU load




Number of replies




Response Time (in milliseconds)




Number of mistakes




I have suspicions that he could handle 30,000 requests, but I had to move on, so I could not verify this. In general, by this time I already knew that I would use Python for my project, so I needed frameworks in other languages ​​just for comparison.

3. Files / Siege / Intel Core i7-4770 Quad-Core Haswell, 32 GB DDR3 RAM


As I wrote above, I am not completely satisfied with my work, so I went to bed with a sense of accomplishment, and woke up with the thought “I need more tests!”. Giving a line of text to each request is certainly good, but this is not the only function of the web server, so we will distribute the files.

For this test, I used 10 VPS to create the necessary load. Experimentally, I found that on 1 VPS DigitalOcean, on average, a 100Mbps channel is allocated. I had a server with a 1Gbps channel and I had to fully load it. The files for distribution were images from an online store in the amount of 10,000 pieces, of different sizes. To create the load, I used the siege utility with the following parameters:

siege -i -f fileslist.txt -c 55 -b -t1M

A list of files is stored in filelist.txt, 55 connections are established and through them we begin to hammer the server with requests within 1 minute. Files are randomly selected from the fileslist.txt list. It is definitely worth considering that this test runs on 10 machines at the same time, which means that we are installing not 550, but 550 simultaneous connections. Moreover, I constantly changed this option from 5 to 55 in increments of 5, thereby increasing the load on the server, and establishing from 50 to 550 simultaneous connections.

Here's what we get ( along the X axis - the number of simultaneous connections ):

Number of completed requests



The number of processed requests per second



CPU load (%)



RAM consumption (% of 32Gb)



Communication channel load (megabytes per second)



Average request response time (in seconds)



In this test, I added RAM consumption as well as the nginx web server for comparison. Here the bottleneck is the communication channel, and the 1st core is enough to load this entire channel in 1Gbps.

Results (in brackets the number of processed requests without errors):

  1. Nignx ( 100175 )
  2. Eventlet ( 97925 )
  3. Gevent ( 96918 )
  4. Express.js ( 96162 )
  5. Twisted ( 85733 )
  6. Tornado ( 83241 )

4. GridFS / Siege / Intel Core i7-4770 Quad-Core Haswell, 32 GB DDR3 RAM


This could be the end of the article, but I wanted to use MongoDB GridFS in my project, so I decided to see how performance would change with its use. This test is similar to the 3rd one, except that I uploaded all the images in the amount of 10,000 in MongoDB and rewrote the web servers so that they would distribute files from the database. So what do we get:

Number of completed requests



The number of processed requests per second



CPU load (%)



RAM consumption (% of 32Gb)



Communication channel load (megabytes per second)



Average request response time (in seconds)



Number of mistakes



During the test, Gevent had answers with errors, so I added a graph “Number of errors”. In general, GridFS can be used, but it should be borne in mind that the database itself creates a considerable load on the CPU, and I had 7 free cores at its disposal, when everything is much simpler with the file system.

Results (in brackets the number of processed requests without errors):

  1. Express.js ( 88714 )
  2. Gevent ( 86182 )

findings


  • MacBook Pro Retina really works out 9 hours on a single charge.
  • Node.js is not the only tool, some say, for developing network applications.
  • Gevent produces very good performance.
  • Making an article takes more time than writing it.
  • Performance testing is a complex process that takes a lot of time.

Seriously, it all depends on the conditions under which your project will work. You can conduct a huge number of tests, but when the service is written, everything will most likely be completely different. For example, if you increase the number of pictures from 10,000 to 1,000,000, the performance of the hard drive, rather than the communication channel, becomes a bottleneck.

Materials

If you decide to conduct your own testing or study mine in more detail, then this list should help you.

Reports

Full reports with individual charts and numbers can be downloaded at these links:

  1. Text / Httperf / VPS 1 CPU, 512Mb RAM
  2. Text / Httperf / Intel Core i7-4770 Quad-Core Haswell, 32 GB DDR3 RAM
  3. Files / Siege / Intel Core i7-4770 Quad-Core Haswell, 32 GB DDR3 RAM
  4. GridFS / Siege / Intel Core i7-4770 Quad-Core Haswell, 32 GB DDR3 RAM

Tools

In my tests, I used:


Frameworks

The tests involved:


Thank you all for your attention.

Follow me on Twitter , I talk about working in a startup, my mistakes and the right decisions, about python and everything related to web development.

PS I'm looking for developers in the company, the details are in my profile .

Also popular now: