Python、JavaScript和Rust的Web性能比较 - Alex

能修谨
2023-12-01

Python使用FastApi测试;Node.JS使用Fastify;Rust则使用Actix。

选择的Python和Node框架,是在搜索 "最快的<某语言>api "时得到的最高结果;Rust的Actix是一直高度维护的。

测试的基础很简单;在我的MacBook Pro M1上,每个框架处理来自网络服务器的5000个基本 "Hello, World "响应需要多长时间?

我用来运行测试的代码非常简单,显然,我们只关心速度:

 

Python

<span style="color:#333333"><span style="background-color:#f5f5f5">客户端代码:
<strong>import</strong> requests
from requests.adapters <strong>import</strong> HTTPAdapter
from requests.packages.urllib3.util.retry <strong>import</strong> Retry

MAX_RETIES = 3

def create_retriable_session():
    s = requests.Session()
    retries = Retry(
        total=MAX_RETIES,
    )
    s.mount('http:<span style="color:#0000aa"><em>//', HTTPAdapter(max_retries=retries))</em></span><span style="color:black">
    s.mount('https:</span><span style="color:#0000aa"><em>//', HTTPAdapter(max_retries=retries))</em></span><span style="color:black">
    <strong>return</strong> s


def main():
    s = create_retriable_session()

    <strong>for</strong> _ in range(0, 5000):
        s.get(</span><span style="color:#00bb00">"http://127.0.0.1:8000/"</span><span style="color:black">)
</span></span></span>

服务器端,使用fastapi:

<span style="color:#333333"><span style="background-color:#f5f5f5">from fastapi <strong>import</strong> FastAPI

app = FastAPI()


@app.get(<span style="color:#00bb00">"/"</span><span style="color:black">)
async def root():
    <strong>return</strong> {</span><span style="color:#00bb00">"message"</span><span style="color:black">: </span><span style="color:#00bb00">"Hello World"</span><span style="color:black">}
</span></span></span>

运行服务器:

uvicorn main:app

测试结果:

<span style="color:#333333"><span style="background-color:#f5f5f5">5.22 s ± 221 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
</span></span>

下面是使用另外一个框架Fastfy使用异步后的代码:

<span style="color:#333333"><span style="background-color:#f5f5f5"><strong>const</strong> fastify = require('fastify')({logger: false})

<strong>const</strong> PORT = 8000;

fastify.get('/', async (request, reply) => {
    <strong>return</strong> {message: 'Hello World'}
})

<strong>const</strong> start = async () => {
    <strong>try</strong> {
        await fastify.listen(PORT)
    } <strong>catch</strong> (err) {
        fastify.log.error(err)
        process.exit(1)
    }
}
start()
</span></span>

再次测试结果:

<span style="color:#333333"><span style="background-color:#f5f5f5">4.49 s ± 84.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
</span></span>

比较结果:

FastApi每秒处理约957.85次,Fastfy每秒处理1113.59次。

  

Rust

<span style="color:#333333"><span style="background-color:#f5f5f5">use actix_web::{App, get, HttpResponse, HttpServer, Responder};

#[get(<span style="color:#00bb00">"/"</span><span style="color:black">)]
async fn hello() -> impl Responder {
    HttpResponse::Ok().body(</span><span style="color:#00bb00">"{\"message\": \"Hello World\"}"</span><span style="color:black">)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::<strong>new</strong>(|| {
        App::<strong>new</strong>()
            .service(hello)
    })
        .bind(</span><span style="color:#00bb00">"127.0.0.1:8000"</span><span style="color:black">)?
        .run()
        .await
}
</span></span></span>

测试结果:

<span style="color:#333333"><span style="background-color:#f5f5f5">4.32 s ± 58.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
</span></span>

比较结果:

我们再次看到,Rust比python快,也比Fastify快,Rust能够每秒处理1157.41个请求,每秒比Fastify快44个请求,比FastApi每秒快200个请求。

   

Node.js

只是为了好玩,Express是最常见的节点框架,所以我也想测试一下,Express比fastify的功能更全面,所以我估计它也会更慢。

<span style="color:#333333"><span style="background-color:#f5f5f5"><strong>const</strong> express = require('express')
<strong>const</strong> app = express()
<strong>const</strong> port = 8000

app.get('/', (req, res) => {
    res.json({message: <span style="color:#00bb00">"Hello World"</span><span style="color:black">})
})

app.listen(port, () => {
    console.log(`Example app listening at http:</span><span style="color:#0000aa"><em>//localhost:${port}`)</em></span><span style="color:black">
})
</span></span></span>

 

测试结果:

<span style="color:#333333"><span style="background-color:#f5f5f5">4.88 s ± 152 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
</span></span>

而且确实比fastify要慢。

  

结论

Rust绝对是最快的选择,但它是最好的吗?我不确定我是否能回答这个问题,因为98%的情况下这要取决于。你的团队知道什么?该框架有你需要的功能吗?如果没有,你能建立它吗?如果你没有一个专家团队,学习起来有多容易?该框架在4-5年内存在的可能性有多大?

这些测试有一些注意事项,它们是在Python中运行的,所以它们只能以Python发出请求的速度运行,而且它们不是多线程的,所以框架也可能不会使用多线程来响应,这取决于Python请求库中的会话工作方式。另外,一般来说,node是单线程的,node用队列来伪造并发,但是有一种方法可以解决这个问题,那就是用workers,它允许你在不同的线程上运行多个服务器,这取决于CPU有多少逻辑核心,这在生产中非常有用,因为它有巨大的性能提升,但同样,这些测试不能从中受益。

这篇文章的重点不是让你转到Actix/Rust的生产服务器上,重点是展示我在学习新东西时喜欢的一种简单的方法,并希望展示测试并不总是要严肃或复杂。

 类似资料: