0%

一个 Requests 的性能问题

Requests 是 Python 最常用的 HTTP 包,API 封装的精美而且简单易用,不过没想到官网的第一个例子就有严重的潜在性能问题。

公司项目有需求去对用户的网页进行实时抓取,虽然 Python 很慢而且有 GIL,不过我一开始的判断是因为网页抓取是个 IO Bound 的操作,即使是单机,每秒并发度也应该至少 > 100。然而,性能测试发现能承受的每秒并发度 < 5…

大概源码是

1
2
r = requests.get($SOME_URL)
text = r.text # 慎用

原因是这样,为了用起来方便,如果想要的是 text (str) 那么 requests 会做一次对原始字节流的解码,如果网页给出了编码可以直接用,但是有相当一部分的网页没有指定编码,这时候 requests 会在内部调用 chardet 去猜最可能的编码,这个包相当慢,而且是 CPU Bound 的,Python 的 GIL 在这种时候就雪上加霜。

requests 的 issues 每隔一段时间就有人报告这个问题,比如 response.text is too slow, 我认为还是应该引起官方重视的,在性能重要的场景相当容易用错!

解决办法是不要直接用 text, 改用 content (binary),然后调用更快的 chardet 包

Python 用起来很爽,自带电池,不过应用在要求性能的生产环境还是需要更加详细的设计,评估和性能测试。