Python、JavaScript和Rust的Web性能比较

liftword1周前 (05-14)技术文章9

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

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

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

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

Python

客户端代码:

<b>import</b> requests

from requests.adapters <b>import</b> HTTPAdapter

from requests.packages.urllib3.util.retry <b>import</b> Retry


MAX_RETIES = 3


def create_retriable_session():

s = requests.Session()

retries = Retry(

total=MAX_RETIES,

)

s.mount('http:<font><i>//', HTTPAdapter(max_retries=retries))</i></font><font>

s.mount('https:</font><font><i>//', HTTPAdapter(max_retries=retries))</i></font><font>

<b>return</b> s


def main():

s = create_retriable_session()


<b>for</b> _ in range(0, 5000):

s.get(</font><font>"http://127.0.0.1:8000/"</font><font>)

</font>

服务器端,使用fastapi:

from fastapi <b>import</b> FastAPI


app = FastAPI()


@app.get(<font>"/"</font><font>)

async def root():

<b>return</b> {</font><font>"message"</font><font>: </font><font>"Hello World"</font><font>}

</font>

运行服务器:

uvicorn main:app

测试结果:

5.22 s ± 221 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

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

<b>const</b> fastify = require('fastify')({logger: false})


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


fastify.get('/', async (request, reply) => {

<b>return</b> {message: 'Hello World'}

})


<b>const</b> start = async () => {

<b>try</b> {

await fastify.listen(PORT)

} <b>catch</b> (err) {

fastify.log.error(err)

process.exit(1)

}

}

start()

再次测试结果:

4.49 s ± 84.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

比较结果:

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

Rust

use actix_web::{App, get, HttpResponse, HttpServer, Responder};


#[get(<font>"/"</font><font>)]

async fn hello() -> impl Responder {

HttpResponse::Ok().body(</font><font>"{\"message\": \"Hello World\"}"</font><font>)

}


#[actix_web::main]

async fn main() -> std::io::Result<()> {

HttpServer::<b>new</b>(|| {

App::<b>new</b>()

.serb> express = require('express')

<b>const</b> app = express()

<b>const</b> port = 8000


app.get('/', (req, res) => {

res.json({message: <font>"Hello World"</font><font>})

})


app.listen(port, () => {

console.log(`Example app listening at http:</font><font><i>//localhost:${port}`)</i></font><font>

})

</font>

测试结果:

4.88 s ± 152 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)Rust

use actix_web::{App, get, HttpResponse, HttpServer, Responder};


#[get(<font>"/"</font><font>)]

async fn hello() -> impl Responder {

HttpResponse::Ok().body(</font><font>"{\"message\": \"Hello World\"}"</font><font>)

}


#[actix_web::main]

async fn main() -> std::io::Result<()> {

HttpServer::<b>new</b>(|| {

App::<b>new</b>()

.service(hello)

})

.bind(</font><font>"127.0.0.1:8000"</font><font>)?

.run()

.await

}

</font>

测试结果:

4.32 s ± 58.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

比较结果:

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

Node.js

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

<b>const</b> express = require('express')

<b>const</b> app = express()

<b>const</b> port = 8000


app.get('/', (req, res) => {

res.json({message: <font>"Hello World"</font><font>})

})


app.listen(port, () => {

console.log(`Example app listening at http:</font><font><i>//localhost:${port}`)</i></font><font>

})

</font>

测试结果:

4.88 s ± 152 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

而且确实比fastify要慢。

结论

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

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

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

相关文章

代码示例:Python 调用并执行 JS

经常做爬虫需要扣JS的老铁一定很熟悉这段操作,通过execjs调用并执行 JS 对一些加解密的处理非常有用。在此记录一下相互学习交流。以下是具体步骤:1、安装 execjspip install py...

如何使用 Scrapy 执行 JavaScript

大多数现代网站都使用客户端 JavaScript 框架,例如 React、Vue 或 Angular。在没有服务器端渲染的情况下从动态网站抓取数据通常需要执行 JavaScript 代码。我已经抓取了...

Python爬虫高级之JS渗透登录新浪微博 | 知了独家研究

小伙伴们看到标题可能会想,我能直接自己登陆把登陆后的cookie复制下来加到自定义的请求头里面不香嘛,为什么非要用python模拟登录的过程?如果我们是长期爬取数据,比如每天早上中午和晚上定时爬取新浪...

在pyside的QWebEngineView中和javascript通信

在pyside2中可以使用QtWebChannel 使QWebEngineView和前端页面的javasccript通信代码:from PySide2.QtWebChannel import QWeb...

网页数据如何获取,带你走近JS逆向,完全入门级!

在这个大数据时代,我们眼睛所看到的百分之九十的数据都是通过页面呈现出现的,不论是PC端、网页端还是移动端,数据渲染还是基于html/h5+javascript进行的,而大多数的数据都是通过请求后台接口...

python散装笔记——151: 非官方Python实现

1: IronPythonIronPython是一个开源的Python实现,专为.NET和Mono设计,使用C#编写,采用Apache License 2.0授权。它依赖于DLR(动态语言运行时)。目...