当前位置: 首页 > 后端技术 > Python

无脑吹FastAPI性能碾压Flask?关于网上不恰当的性能对比和令人困惑的自测结果

时间:2023-03-25 22:11:15 Python

不止一次听说过,有一个FastAPI框架,性能碾压Flask,直接赶超Golang,但是我从来没有测试过,我什么都没有测试今天的结果。我不知道哪里出了问题,结果令人震惊。为了考前偷懒,自然想在网上找前辈们的测试代码作为参考。百度排名前几的FastAPI和Flask性能测试附代码如下:FastAPI、Flask、Golang性能测试Flask、Django、Tornado、FastAPIPythonWeb并发测试flask、tornado、fastapi压测对比(web框架)简单看了下,没明白为什么用uvicorn启动FastAPI,却只用Flask自带的启动方式,为什么其他WSGI服务器不行?我觉得这应该是个问题,更何况两者不是一个级别的框架(FastAPI是基于Starlette的,是应该和Flask比较的框架),就算比较了,也应该用类似的启动方法。?uvicorn是第三方的ASGI服务器,Flask应该是用第三方的WSGI服务器启动的吧?使用自带的WSGI服务器可能不太公平。本来想用gunicorn启动Flask做对比,后来发现不兼容Windows,所以改成waitress,类似WSGI框架。启动测试环境:Win10Python3.8.9所有依赖库均为最新版本,在网上用AB测试。我的电脑没有安装Apache,所以用了另外一个测试工具siege。测试方法不限连接数,测试时间为10秒。命令如下:./siege.exe-b-t10shttp://127.0.0.1:5000/测试代码和之前找到的一样。借鉴两个官网的例子,OutputHelloWorld,稍作修改,将启动代码写入文件,这样就不需要使用命令行启动了。FlaskfromflaskimportFlaskfromwaitressimportserveapp=Flask(__name__)@app.route('/')defindex():return{'message':'helloworld'}if__name__=='__main__':app.run(host='0.0.0.0')#serve(app,host='0.0.0.0',port=5000)FastAPIfromfastapiimportFastAPIimportuvicornapp=FastAPI()@app.get("/")asyncdefread_root():return{"Hello":"World"}if__name__=="__main__":uvicorn.run(app,host="0.0.0.0",port=5000)测试结果鉴于网上的文章有,所以我也测试了下看一下使用Flask自带的启动方式的结果。另外,我也测试了使用异步FastAPI的结果(只是加了async,实际中应该没什么用,文档里写的很清楚,只有在函数内部使用了异步函数,需要同步返回的时候,也就是它需要在Async中,只有在内部使用await时才需要定义)。结果如下:flaskTransactions:4579hitsAvailability:100.00%Elapsedtime:9.15secsDatatransferred:0.11MBResponsetime:0.03secsTransactionrate:500.66trans/secThroughput:0.01MB/secConcurrency:14.93Successfultransactions:4579Shortest10transaction:0.test10transaction:0.Longesttransaction:0.03secsTransactionrate:500.66trans/secThroughput:0.01MB/secflask+waitressTransactions:12598hitsAvailability:100.00%Elapsedtime:10.02secsDatatransferred:0.31MBResponsetime:0.01secsTransactionrate:1257.03trans/secThroughput:0.03MB/secConcurrency:14.89Successfultransactions:12598Failedtransactions:0.03testtransaction:0.03S交易0.00fastapi+uvicornTransactions:5278hitsAvailability:100.00%\Elapsedtime:9.05secsDatatransferred:0.09MBResponsetime:0.03secsTransactionrate:583.20trans/secThroughput:0.01MB/secConcurrency:14.93Successfultransactions:5278Failedtransactions:0Longesttransaction:0.11Shortesttransaction:0.01fastapi+uvicorn+asyncTransactions:5876hitsAvailability:100.00%\Elapsedtime:9.31secsDatatransferred:0.10MBResponsetime:0.02secsTransactionrate:631.22trans/secThroughput:0.01MB/secConcurrency:14.84Successfultransactions:5870.hor01Slong2transactions:test0.10Sfailedtransactions:5870.0.02secsTransactionrate:631.22trans/sec吞吐量:0.01MB/sec特拉nsaction:0.00从Transactionrate也就是请求处理率可以看出Flask直接启动的结果比FastAPI稍微差一点(500:583/631)FastAPI和async没有太大区别(583:631)Flask使用waitressWSGI服务器启动结果比没有(1257:500)快2.5倍,也比FastAPI快2倍左右。这个结果和别人的测试完全不一样,和我的估计差距很大。怎么了?预计Flask会比直接启动FastAPI慢,但是用waitressWSGIserver启动快那么多肯定不正常。于是查看了两家初创公司的源码,发现waitress默认是4线程,uvicorn默认是1线程。..我不得不将Flask更改为1个线程并重新测试serve(app,host='0.0.0.0',port=5000,threads=1)结果如下:Transactions:7492hitsAvailability:100.00%Elapsedtime:9.07secsDatatransferred:0.19MB响应时间:0.02秒交易率:825.84trans/sec吞吐量:0.02MB/sec并发:14.89成功交易:7492失败交易:0最长交易:0.07最短交易:0.01Modifyuvicornto4threadsandretestuvicorn"test-fast.run:app"="0.0.0.0",port=5000,workers=4)#需要在同级目录下新建`pyproject.toml`文件,内容为:[tool.poetry.scripts]start="test-fastapi:start"结果如下:Transactions:7782hitsAvailability:100.00%Elapsedtime:9.24secsDatatransferred:0.13MBResponsetime:0.02secsTransactionrate:842.39trans/secThroughput:0.01MB/secConcurrency:14.92Successfultransactions:7782Failedtransactions:0Longesttransaction:0.15Shortesttransaction:0.00可以看出Flask使用waitressWSGI服务器单线程启动结果比没有(825)快650%:,它也比FastAPI(825:583/631)快得多。uvicorn以4个线程开始,改进非常小(842:583/631)。它不如女服务员单线程快。这个结果出乎意料。我现在有点不自信。我的测试过程有问题吗?从理论上讲,这没有意义。uvicorn开启4个线程后,结果只有1倍多,而waitress开启4个线程快了2倍多,也就是说4个线程没有得到充分利用,uvicorn的单线程处理能力更强。我不知道。之所以结果差异如此之大,可能是测试工具的原因。毕竟别人用的AB也是规定并发数的。我用的siege没有并发限制。而且uvicorn文档中也提到可以使用Gunicorn来管理进程,性能可能会有所提升。由于设备原因,我不会测试它。更换工具并重新测试后,我简直不敢相信这个结果。第二天,换了嘿压测工具再次测试,20并发10秒\hey_windows_amd64.exe-c20-z10shttp://127.0.0.1:5000/结果如下:flaskSummary:Total:10.0802secsSlowest:0.1169secsFastest:0.0056secsAverage:0.0389secsRequests/sec:512.5894flask+waitress1线程Summary:Total:10.0128secsSlowest:0.0721secsFastest:0.0013secsAverage:0.0199secsRequests/sec:1006.4087fastapi+uvicorn1线程Summary:Total:10.0161secsSlowest:0.0888secsFastest:0.0031secsAverage:0.0225secsRequests/sec:886.4733fastapi+uvicorn+async1线程Summary:Total:10.0218secsSlowest:0.0808secsFastest:0.0057secsAverage:0.0210secsRequests/sec:951.3288flask+waitress4线程Summary:Total:10.0051secsSlowest:0.0912secsFastest:0.0016secsAverage:0.0134secsRequests/sec:1486.4384fastapi+uvicorn4threadsSummary:Total:10.0386secsSlowest:0.0925secsFastest100test:0.0ecsAverage:0.0154secsRequests/sec:1292.3074fastapi+uvicorn+async4threadsSummary:Total:10.0108secsSlowest:0.0853secsFastest:0.0016secsAverage:0.0134secsRequests/sec:93489PS从平均响应时间比直接启动结果:和QFlas8PS9结果:FastAPI启动的结果相差将近一半。FastAPI使用异步async,但还是有一些改进。Flask使用waitressWSGI服务器启动和FastAPI使用uvicorn+asynchronous的结果基本一致。Flask使用waitressWSGIserver单线程启动结果。赶紧把这个测试写在最后吧。做这个测试的初衷是为了反驳上面提到的理由。我只想说,在对比测试的时候应该使用第三方的WSGI服务器来启动Flask。我对最终的测试结果也有点困惑。真的,看到这篇文章的朋友最好自己测试一下。另外,性能测试一定要增加基础功能,至少是数据接收、处理、返回的全过程。仅测试HelloWorld不具有代表性。我再说一点,网上吹嘘FastAPI的人太多了,也不否认它的优点,比如支持异步,ws,自动生成文档,强调变量类型的声明等等,但是没有需要踩Flask的性能。写了几个小时的课文和考卷,我自由了。