ss
Navigate back to the homepage

Spaceout

Interstellar design

UX/UI design, Web and Native App develeopement.

about meHow it's doneContact
Link to $https://www.facebook.com/spaceout/Link to $https://twitter.com/spaceoutLink to $https://www.instagram.com/spaceout/Link to $https://blog.spaceout.pl/Link to $https://dribbble.com/spaceoutLink to $https://behance.com/spaceoutLink to $https://github.com/massivDash/
Sever Analysis

Static race

by
Luke Celitan
category: post, reading time: 5 min

Static race, who will become the static king ?

In the world of web development, the choice of server framework can significantly impact the performance and efficiency of a website. In the most real life scenarios you will need an instance to serve static assets to the client whatever application you are building. Html, css, jss, images and others static assets are the backbone of any frontend.

Static serving is the most cheapest and most reliable way to deliver content on the intrent so far. Until you start moving your assetes to CDN providers, most likely you will decide the serve the static files localy.

I decided to create a simple test to find out which serving option is the most performant on my own.

Today, we’re diving into a comparative analysis of four different server frameworks: Actix, Express, Nginx, and Restify. The focus of this comparison is on the average wait times for a browser to download resources from the server, including HTML and images.

The data presented in the data analysis reflects the results from 2000 calls per each server requesting a simple HTML site with a single 12.7MB image.

This metric is crucial as it gives us insight into the responsiveness of each server framework under load. Additionally, the ‘HTML + Image Stack’ represents the total time needed to stream the website to the client, including all resources, with 1000 calls each.

Test Methodology

The test was straightforward: open a static website consisting of a simple HTML page (200kb) and a single image (12.7mb) and download it fully to the client browser.

All applications are running on the same machine, boasting 2GB of RAM and SSD storage, and were tested sequentially to ensure fairness. Each application has a SSL let’s encrypt certificate and is located in the same region (Warsaw).

The links for reference

All application were created with minimal reproduction except for rust based actix, astro x website is a another rust based project, I am working on, i has some more middlewares but still serves as a static server as well.

Html markup used in the test

1<!DOCTYPE html>
2<html>
3 <head>
4 <title>Express Static Files Test</title>
5 </head>
6 <body>
7 <h1>Nginx Static Files Test</h1>
8 <img src="./webdev2.png" alt="Web Development Image" />
9 </body>
10</html>

Test Picture

This is the test picture we will be stressing my hosting with. Here obviously optimized, but in the test the upscaled 12.7MB version was used. Definetly chosen in order to get some bigger diffrences in how framework utilize bigger i/o operations.

Web Dev Commandos

The Test

A simple simulation of a desepearte user clicking refresh 1000 times and waiting each time before the images finshes to load, created using playwright e2e framework

1import { chromium, Browser, Page } from 'playwright';
2import { test } from '@playwright/test';
3import { PlaywrightHar } from 'playwright-har';
4
5test('should reload page 1000 times and generate HAR file', async () => {
6 test.setTimeout(1200000000);
7 const browser = await chromium.launch();
8 const context = await browser.newContext({
9 extraHTTPHeaders: {
10 'Cache-Control': 'no-cache, no-store, must-revalidate',
11 },
12 recordHar: { path: './hars/nginx.har' },
13 });
14 const page = await context.newPage();
15
16 const playwrightHar = new PlaywrightHar(page);
17 await playwrightHar.start();
18
19 await page.goto('https:/nginxtest.spaceout.pl');
20 await page.waitForLoadState('networkidle');
21 await page.waitForFunction(() => {
22 const images = Array.from(document.querySelectorAll('img'));
23 return images.every((img) => img.complete);
24 });
25
26 const reloads = Array.from({ length: 1000 });
27 for await (const _ of reloads) {
28 await page.reload();
29 await page.waitForFunction(() => {
30 const images = Array.from(document.querySelectorAll('img'));
31 return images.every((img) => img.complete);
32 });
33 await page.waitForLoadState('networkidle');
34 }
35
36 await playwrightHar.stop('./hars/nginx.har');
37 await browser.close();
38});

Data Analysis

Fastest and slowest runs

Actix, a server framework written in Rust, has been turning heads with its impressive HTML return times. It clocked in at a blistering 34.154ms, showcasing the efficiency of Rust’s design for concurrent web services. Nginx, the stalwart of high-performance web servers, is hot on Actix’s heels with a return time of 34.349ms. This close competition highlights the advancements in web server technology and the fine margins that separate the top performers.

When it comes to handling larger files, Nginx takes the lead. It served a 12.7MB file in just 596.061ms, edging out Actix, which completed the task in 612.17ms. This demonstrates Nginx’s robustness and its ability to handle a mix of tasks without breaking a sweat.

Node.js-based solutions, while versatile and popular, show significantly higher maximum scores in these benchmarks. The Express framework, for instance, has gained notoriety for being slower in HTML delivery. Similarly, Restify leads the pack in the image serving category, albeit on the slower end of the spectrum.

Average serving time

Avarage wait times for a browser to download the resource from the server. “All” column represents all 2000 calls for html and one 12.7mb image.

The html + image stack represents the total time needed to stream the website the client with all resources, 1000 calls each.

On an avarage the fastest serving framework is the rust based actix server, with an avarage serving time of 559.72ms (0.55s), it is also a winner in the the html (45.48ms) and image category (972.60ms).

In details comparison.

The min, avg, max analysis suggests that the Actix is the most preformant framework. I have prepared the funnel and scatter charts to help anlayse the overall spread and stability of each framework.

Actix (https://actix.rs/)

Actix is a powerful, pragmatic, and extremely fast web framework for Rust. It is built on the Actor Model, which allows applications to be written as a group of independently executing but cooperating “Actors” that communicate via messages. This model offers high performance and scalability through its asynchronous programming model and lightweight design

Actix is the average request time category winner, with solid numbers to back it up, for 1000 requests most of them were delivered better than the competition in both html and image file

The scatter graph indicates solid and consistent content delivery, overall it looks like the most stable way to server static content on the web.

Nginx (https://www.nginx.com/)

Nginx, pronounced as “engine-x”, is a versatile web server that has gained popularity for its high performance, stability, and low resource usage. Initially released in 2004 by Russian developer Igor Sysoev, Nginx was designed to address the C10k problem, which is the challenge of handling ten thousand concurrent connections. Over the years, it has evolved to serve a variety of roles including a reverse proxy, load balancer, mail proxy, and HTTP cache.

Nginx is the fastest responder in this test, will overall solid scores. Definetly a good choice if possible, the data indicates it provides stable and consistent delivery. On avarage he was still 17.67%* behind Actix framework, making it second best choice for serving static content

1* slower % calculation
2
3Difference = Score - Base = 599 ms - 509.040587 ms = 89.959413 ms
4Percentage slower = (Difference / Base) * 100 = (89.959413 ms / 509.040587 ms) * 100 ≈ 17.67 %

Express

Express.js, often referred to simply as Express, is the most popular backend web application framework for Node.js. Renowned for its minimalist and unopinionated approach, it offers a robust set of features for web and mobile applications.

Express times are much more hectic and spread out than the nginx and actix, with a 25.65% slower times than rust based actix.

Restify (https://restify.com/)

Restify.js is a Node.js web service framework designed for building efficient and scalable RESTful web services. It is optimized for introspection and performance, making it a suitable choice for production use at scale. Restify.js focuses on providing a semantically correct implementation of REST, adhering closely to HTTP and REST specifications, which is reflected in its support for RFC standards throughout its codebase and documentation.

The last runner on the list is restify which is 27.16% slower than actix. He really tried to beat express but in the end express image and average delivery was 1.51% slower than express

Final thoughts

It looks like the best choice for serving static files is the Actix framework, but I would not be quiting on nginx just yet. Ngnix is still a great option especially with its build in features like load balancers, reverse proxy and others. If you are not building a rust based application the Nginx is the way to go.

Node frameworks showed significantly weaker scores than the “native” drivers, this was especially seen on the large image transfers. In my opinion if the performance is what you are looking for the you should try to use underlying services for serving static content.

The raw test data can be accessed at https://github.com/MassivDash/staticRace

s