Sanic是基于uvloop的异步web框架,其性能个人觉得比Py三大框架强。
安装wrk压测工具
git clone https://github.com/wg/wrk.git
make
计算机环境
python3.6.8
tornado==6.0.2
sanic==19.3.1
cpu Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
测试语句:
wrk -t10 -d1m -c200 http://127.0.0.1:8080
1. 测试python标准库自带的HttpServer
from http.server import BaseHTTPRequestHandler
from urllib import parse
class GetHandler(BaseHTTPRequestHandler):
def do_GET(self):
message = "Hello World"
self.send_response(200)
self.end_headers()
self.wfile.write(message.encode('utf-8'))
if __name__ == '__main__':
from http.server import HTTPServer
server = HTTPServer(('localhost', 8080), GetHandler)
server.serve_forever()
wrk -t10 -d1m -c200 http://127.0.0.1:8080
结果
Running 1m test @ http://127.0.0.1:8080
10 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 6.25ms 61.93ms 1.67s 99.04%
Req/Sec 556.71 549.62 1.76k 67.14%
4261 requests in 1.01m, 424.44KB read
Socket errors: connect 0, read 4261, write 0, timeout 0
Requests/sec: 70.28
Transfer/sec: 7.00KB
每秒请求70
2. 测试sanic
from sanic import Sanic
from sanic.response import json, text
import asyncio
app = Sanic()
@app.route("/")
async def test(request):
asyncio.sleep(1)
return json({"message": "hello world"})
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=False, port=8080, access_log=False, workers=1)
这里测试一个进程也就是一个cpu的,测试结果
Running 1m test @ http://127.0.0.1:8080
10 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 10.58ms 2.46ms 48.66ms 86.05%
Req/Sec 1.90k 343.11 4.43k 74.63%
1136502 requests in 1.00m, 146.32MB read
Requests/sec: 18915.42
Transfer/sec: 2.44MB
sanic每秒请求大概1.9w
3. 测试tornado
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8080)
tornado.ioloop.IOLoop.current().start()
tornado并没有返回json了,直接测试性能,测试结果:
Running 1m test @ http://127.0.0.1:8080
10 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 66.14ms 9.37ms 159.04ms 91.26%
Req/Sec 304.24 88.16 600.00 30.50%
181609 requests in 1.00m, 35.85MB read
Requests/sec: 3021.95
Transfer/sec: 610.88KB
每秒请求3k
4 测试go标准库net/http
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"runtime"
"time"
)
type Hello struct {
}
type Msg struct {
Message string
}
func (h Hello) ServeHTTP(w http.ResponseWriter, r *http.Request) {
time.Sleep(1)
msg := Msg{Message: "Hello world"}
s, _ := json.Marshal(msg)
fmt.Fprint(w, string(s))
}
func main() {
h := Hello{}
runtime.GOMAXPROCS(1)
err := http.ListenAndServe("localhost:8080", h)
if err != nil {
log.Fatal(err)
}
}
这里限制核心数为1核,和sanic平级。结果如下
Running 1m test @ http://127.0.0.1:8080
10 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 6.14ms 17.53ms 343.37ms 98.64%
Req/Sec 4.54k 821.84 18.65k 80.78%
2713334 requests in 1.00m, 367.44MB read
Requests/sec: 45151.63
Transfer/sec: 6.11MB
每秒4.5w,其实如果sanic改为多进程,go也改为没有cpu限制,他们之间还是会相差2倍。
5 测试node.js
var http = require('http');
http.createServer(function (request, response) {
// 发送 HTTP 头部
// HTTP 状态值: 200 : OK
// 内容类型: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'});
// 发送响应数据 "Hello World"
response.end('Hello World\n');
}).listen(8080);
Running 1m test @ http://127.0.0.1:8080
10 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 5.86ms 1.70ms 85.42ms 95.21%
Req/Sec 3.46k 494.21 5.75k 89.76%
2065598 requests in 1.00m, 307.31MB read
Requests/sec: 34378.55
Transfer/sec: 5.11MB
每秒3.4w左右,由于node.js使用的也是libuv,但是python本身语言还是慢了。或者说,Sanic是一个框架,逻辑也比go的http和node的http模块逻辑要复杂的多,执行时间自然足药更多的时间。
uvloop
sanic是使用的uvloop作为asyncio的loop实现,uvloop本身非常快,他是Cython写的。如果使用c语言写的http解析器,那么它实现的http的性能和node.js持平, 和go也有的拼。
https://magic.io/blog/uvloop-blazing-fast-python-networking/
思考
是否可以将业务逻辑之外的,用C实现,再Python语言绑定,如上图,http解析器使用httptools实现,达到最大化利用计算机性能?
虽然python的执行速度没那么快,但是均衡开发速度,选择Python,你会有更多的时间做其它事情。
-----------------<如文章有不正确的地方或者你有什么建议,欢迎在下方评论>-----------------
网友评论