Python cherrypy是如何工作的?与tornado相比,当并发度较低时,它能很好地处理请求
我在cherrypy(使用web.py作为框架)和tornado上进行了一项测试,从互联网上检索网页 我有三个测试用例使用Python cherrypy是如何工作的?与tornado相比,当并发度较低时,它能很好地处理请求,python,asynchronous,webserver,tornado,cherrypy,Python,Asynchronous,Webserver,Tornado,Cherrypy,我在cherrypy(使用web.py作为框架)和tornado上进行了一项测试,从互联网上检索网页 我有三个测试用例使用sakege向服务器发送请求(-c表示用户数;-t表示测试时间)。代码低于测试结果 1.web.py(cherrpy) 2.龙卷风同步 3.龙卷风异步 性能分析: tornado同步
sakege
向服务器发送请求(-c表示用户数;-t表示测试时间)。代码低于测试结果
1.web.py(cherrpy)
2.龙卷风同步
3.龙卷风异步
性能分析:
tornado同步要回答问题1 龙卷风是单线程的。如果像在同步示例中那样阻塞主线程,那么在阻塞调用返回之前,单个线程无法执行任何操作。这将同步示例一次限制为一个请求 我对web.py不是特别熟悉,但查看它似乎使用了线程混合,这表明它不限于一次处理一个请求。当第一个请求传入时,它由一个线程处理。该线程将阻塞,直到HTTP客户端调用返回,但其他线程可以自由处理进一步的传入请求。这允许一次处理更多的请求
我怀疑,如果您使用Tornado模拟这种情况,例如,通过将HTTP客户端请求传递到线程池,那么您将看到类似的吞吐量。测试代码中的大部分处理程序时间都花在
client.fetch(…)
-有效地等待连接和套接字上的传入数据-同时不阻止其他潜在的Python线程
因此,您的“性能度量”主要取决于所讨论框架的最大有效处理线程数和“百度”服务器允许从您的IP进行的最大并行连接数
wep.py的CherryPyWSGIServer
web.wsgiserver.CherryPyWSGIServer
副本被默认的web.httpserver.runsimple()
确实默认使用线程-10。线程不会在这里大量增加内存使用。这里,库和Python解释器本身占用了大部分内存。 CherryPyWSGIServer的(10)个处理工作线程都是从一开始就启动的。 可选的web.httpserver.runbasic()也使用线程——通过Python的内置httpserver和
SocketServer.ThreadingMixIn
。这个线程为每个请求启动一个新线程。可能是“无限”的线程数-但每个请求的线程启动都有开销
tornado
异步模式也可能使用更多/无限数量的线程(?),这可能解释了与web.py的区别
您的测试没有说明服务器和处理程序框架本身的执行速度。您可以简单地增加web.py的CherryPyWSGIServer中的最大线程数。并行执行您的客户机.fetch(…)
,在某种程度上需要获得更高的“性能”
要测试服务器/框架的速度(开销成本),只需返回一个字符串、一个数据库查询或从本地内容呈现的典型完整网页
在一个进程中,基于多线程CPython的web&app服务器最终不能使用多个CPU核心(目前服务器硬件上通常使用8个CPU核心),因为CPython中的GIL仅用于某些I/O。因此,如果CPU负载成为一个因素(而不是网络或数据库速度),可以考虑Jython或多进程方法 我非常怀疑您的性能可能会受到
fetch>的限制http://www.baidu.com/)
比您使用的web框架多得多。当你提供静态内容,或者至少是相同的本地生成内容时,试着比较一下。这没关系。我正在比较不同web服务器的性能。“fetch(')”只是一个阻塞代码。cherrypy是从哪里来的?web.py使用cherrypy作为内置的HttpServers当我测试web.py时,我一直在观察cherrpy占用的内存变化。我知道,通常情况下,linux中的线程占用了8m。同时,在开始时,cherrypy占用了1200万,当它处理请求时,只占用了1500万。我不认为它使用多线程。这就是为什么我对cherrypy感到好奇。
siege ip -c20 -t100s server can handle 2747requests
siege ip -c200 -t30s server can handle 1361requests
siege ip -c500 -t30s server can handle 170requests
siege ip -c20 -t100s server can handle 600requests
siege ip -c200 -t30s server can handle 200requests
siege ip -c500 -t30s server can handle 116requests
siege ip -c20 -t100s server can handle 3022requests
siege ip -c200 -t30s server can handle 2259requests
siege ip -c500 -t30s server can handle 471requests
import web
import tornado.httpclient
urls = (
'/(.*)', 'hello'
)
app = web.application(urls, globals())
class hello:
def GET(self, name):
client = tornado.httpclient.HTTPClient()
response=client.fetch("http://www.baidu.com/")
return response.body
if __name__ == "__main__":
app.run()
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.httpclient
from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)
class IndexHandler(tornado.web.RequestHandler):
def get(self):
client = tornado.httpclient.HTTPClient()
response = client.fetch("http://www.baidu.com/" )
self.write(response.body)
if __name__=='__main__':
tornado.options.parse_command_line()
app=tornado.web.Application(handlers=[(r'/',IndexHandler)])
http_server=tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.httpclient
from tornado.options import define, options
define("port", default=8001, help="run on the given port", type=int)
class IndexHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self):
client = tornado.httpclient.AsyncHTTPClient()
response = client.fetch("http://www.baidu.com/" ,callback=self.on_response)
def on_response(self,response):
self.write(response.body)
self.finish()
if __name__=='__main__':
tornado.options.parse_command_line()
app=tornado.web.Application(handlers=[(r'/',IndexHandler)])
http_server=tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()