Home | Benchmarks | Categories | Atom Feed

Posted on Wed 06 October 2021 under Rust

Actix: A Web Framework for Rust

This post is a part of a series exploring Rust-based Web Frameworks.

Actix is a web framework written in Rust. It provides a high-level API for building web applications and helps remove much of the underlying detail of the libraries it's built upon.

The project was started by Nikolay Kim, a Principal Software Engineer at Microsoft in San Francisco, back in 2017. Unfortunately, in January of 2020, Nikolay quit both the Actix project and open source development altogether. It was around this time that Rob Ede, a freelance software developer in London, picked up the lead role in the project.

In September of 2020, Rob released version 3 of Actix, the first major release under his leadership. 45 contributors have joined in with Rob working on the project's primary code repository since the leadership handover in early 2020.

Rob has spent much of 2021 working on the version 4 release of Actix. As of this writing, it's still in beta.

The documentation for Actix is concise, well structured and can be read on a mobile phone without issue. There is an Examples Repository that contains 56 micro-projects across 10 categories. As of this writing they all target version 3 of Actix.

The project is made up of 45K lines of Rust and has amassed almost four million downloads on crates.io. MeiliSearch, a full-text search engine I covered in a recent blog post, uses Actix as does ROAPI, a code-free, static dataset API generator.

In this post, I'll take a look at some of Actix's features and characteristics.

Actix Up & Running

The system used in this blog post is running Ubuntu 20.04 LTS. I'll use Rustup to install Rust version 1.55.0.

$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

I'll then clone Actix's Examples Repository and launch the webchat example.

$ git clone https://github.com/actix/examples
$ cd websockets/chat
$ cargo run

Opening http://localhost:8080/ in a web browser will present you with a form asking you to connect. After doing so, you'll be able to send messages into various chat groups via Websockets.

The above uses 161 lines of Rust and a single 90-line HTML file which relies on jQuery version 1.4.2.

Features & Support

There is asynchronous support for PostgreSQL, MySQL, SQLite, and MSSQL provided by SQLx. There is also support for Diesel, which offers a high-level ORM and Query Builder. Keep in mind, as of this writing, there is a ticket open for adding support for asynchronous operations in Diesel. The Databases documentation explains how to integrate Diesel into an otherwise asynchronous codebase.

There is built-in HTTPS support and contents can be compressed via GZIP, Brotli or Zstandard. Google Chrome 94 doesn't support Zstandard and I couldn't find any support in Python's Requests codebase but curl version 7.71.1, which was released in August last year, does support it. Felix Handte, a Software Engineer working on Data Compression at Facebook, said the firm is using Zstandard to compress the HTTP traffic of their mobile apps.

Actix supports both Websockets, as seen in the example above and HTTP/2.

Actix has the concept of "Application guards" which can be used for hosting multiple domain names from a single web application. They can then be used to route HTTP requests to different areas of the codebase if desired.

There are five templating engines demonstrated in the Examples Repository. They are Askama, Handlebars, Tera, TinyTemplate and Yarte. Yarte comes with out-of-the-box HTML minification support.

Auto-reload is supported via a cargo watch command.

Benchmarking Actix

I came across Rousan Ali's Rust Web Frameworks Benchmark which was carried out with Actix 3.3.2. The benchmark returns "Hello, world!" and quits.

$ git clone https://github.com/rousan/rust-web-frameworks-benchmark.git
$ cat rust-web-frameworks-benchmark/actix/src/main.rs
use actix_web::{get, web, App, HttpServer, Responder};

#[get("/")]
async fn index(_info: web::Path<()>) -> impl Responder {
    format!("Hello, World")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(index))
        .bind("127.0.0.1:8080")?
        .run()
        .await
}

The benchmark is run with Will Glozer's wrk HTTP benchmarking tool using 4 threads and 200 open connections for a duration of 8 seconds. The benchmark ranked Actix version 3.3.2 the fastest against gotham, hyper, Rocket and warp.

The benchmark has some outstanding complaints and Rocket has a new async-supporting version 0.5.0 which should be out of beta soon. Perhaps with the version 4 release of Actix it'll be worth re-examining the performance gaps between these offerings.

Thank you for taking the time to read this post. I offer both consulting and hands-on development services to clients in North America and Europe. If you'd like to discuss how my offerings can help your business please contact me via LinkedIn.

Copyright © 2014 - 2024 Mark Litwintschik. This site's template is based off a template by Giulio Fidente.