一篇关于django,tornado性能测试的非专业性报告

Posted python自动化运维之美

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一篇关于django,tornado性能测试的非专业性报告相关的知识,希望对你有一定的参考价值。

为什么要写这篇文章?

确实是因为博主最近实在太无聊了。闲的蛋疼只能装作很忙的样子。。。故有了这篇。

测试说明

!!这里先说明一下,由于本文出自博主实验环境(windows 笔记本+VirtualBox虚拟linux)条件下,由于条件简陋,且测试代码均比较简单,故测试报告不能保证严谨准确,仅供参考和娱乐。

环境介绍

由于条件简陋,测试环境为本人自用thinkpad x240笔记本电脑(intel core i3 1.9GHZ + 8G内存)+VirtualBOX虚拟机(虚拟环境为centos6.9 64bit 处理器数量1 内存1024M) ,python版本2.7.13 ,django版本1.8.3,tornado版本4.5.2。测试中使用了gunicorn 版本19.7.1。nginx。(多么详细。。。),压力测试工具使用apache自带的 ab工具进行

简单说一下本次测试所写的代码(下面会详细贴出代码),在如此简陋的情况下,测试代码均为hello work状态。(即只利用框架输出index hello word)。

为了保证测试尽量严谨,每个项目压力测试均测试3次以上取平均值(如差异不大随机贴出一次结果。),更换项目后重启虚拟机测试。

不啰嗦了正式开始

一、django、tornado最基本代码测试对比

最基本测试,直接使用项目本身启动程序,即python xxx.py形式 不使用任何转发。

django

 
   
   
 
  1. #由于代码简单 这里只贴出views.py代码,其余代码均为初始化项目后默认未动。(urls.py除添加访问url外无其他修改)

  2. #!/usr/bin/env python

  3. #-*- coding:utf-8 -*-

  4. from django.shortcuts import render

  5. from django.template.context import RequestContext

  6. import os

  7. from django.http import HttpResponse

  8. def index(request):

  9.    return HttpResponse("Hello world ! ")

 
   
   
 
  1. #启动项目,开始测试

  2. [root@centos1 untitled1]# python manage.py runserver 127.0.0.1:8888

  3. Performing system checks...

  4. System check identified no issues (0 silenced).

  5. September 18, 2017 - 06:53:50

  6. Django version 1.8.3, using settings 'untitled1.settings'

  7. Starting development server at http://127.0.0.1:8888/

  8. Quit the server with CONTROL-C

  9. [root@centos1 ~]# ab -n 1000 -c 1000 http://127.0.0.1:8888/index/

  10. This is ApacheBench, Version 2.3 <$Revision: 655654 $>

  11. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/

  12. Licensed to The Apache Software Foundation, http://www.apache.org/

  13. Benchmarking 127.0.0.1 (be patient)

  14. Completed 100 requests

  15. Completed 200 requests

  16. Completed 300 requests

  17. Completed 400 requests

  18. Completed 500 requests

  19. Completed 600 requests

  20. Completed 700 requests

  21. Completed 800 requests

  22. Completed 900 requests

  23. Completed 1000 requests

  24. Finished 1000 requests

  25. Server Software:        WSGIServer/0.1

  26. Server Hostname:        127.0.0.1

  27. Server Port:            8888

  28. Document Path:          /index/

  29. Document Length:        14 bytes

  30. Concurrency Level:      1000

  31. Time taken for tests:   3.010 seconds

  32. Complete requests:      1000

  33. Failed requests:        0

  34. Write errors:           0

  35. Total transferred:      177017 bytes

  36. html transferred:       14000 bytes

  37. Requests per second:    332.22 [#/sec] (mean) ##看这里!!

  38. Time per request:       3010.077 [ms] (mean)

  39. Time per request:       3.010 [ms] (mean, across all concurrent requests)

  40. Transfer rate:          57.43 [Kbytes/sec] received

  41. Connection Times (ms)

  42.              min  mean[+/-sd] median   max

  43. Connect:        0   46 234.5      0    3000

  44. Processing:     3   52 159.3     32    1664

  45. Waiting:        1   49 159.3     29    1662

  46. Total:         20   98 334.0     33    3007

  47. Percentage of the requests served within a certain time (ms)

  48.  50%     33

  49.  66%     34

  50.  75%     36

  51.  80%     38

  52.  90%     46

  53.  95%     82

  54.  98%   1036

  55.  99%   2631

  56. 100%   3007 (longest request)

可以看到默认情况下,吞吐率为332.22 [#/sec]

tornado

 
   
   
 
  1. import textwrap

  2. import tornado.httpserver

  3. import tornado.ioloop

  4. import tornado.options

  5. import tornado.web

  6. import os

  7. from tornado.options import define, options

  8. define("port", default=8888, help="run on the given port", type=int)

  9. class SyncHandler(tornado.web.RequestHandler):

  10.    def get(self, *args, **kwargs):

  11.        self.finish('hello word')

  12. if __name__ == "__main__":

  13.    tornado.options.parse_command_line()

  14.    app = tornado.web.Application(

  15.        handlers=[

  16.            (r"/index", SyncHandler)

  17.        ],

  18.        #debug = True,

  19.    )

  20.    http_server = tornado.httpserver.HTTPServer(app)

  21.    http_server.listen(options.port)

  22.    tornado.ioloop.IOLoop.instance().start()

 
   
   
 
  1. [root@centos1 ~]# python tornadotest.py

  2. [root@centos1 ~]# ab -n 1000 -c 1000 http://127.0.0.1:8888/index

  3. This is ApacheBench, Version 2.3 <$Revision: 655654 $>

  4. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/

  5. Licensed to The Apache Software Foundation, http://www.apache.org/

  6. Benchmarking 127.0.0.1 (be patient)

  7. Completed 100 requests

  8. Completed 200 requests

  9. Completed 300 requests

  10. Completed 400 requests

  11. Completed 500 requests

  12. Completed 600 requests

  13. Completed 700 requests

  14. Completed 800 requests

  15. Completed 900 requests

  16. Completed 1000 requests

  17. Finished 1000 requests

  18. Server Software:        TornadoServer/4.5.2

  19. Server Hostname:        127.0.0.1

  20. Server Port:            8888

  21. Document Path:          /index

  22. Document Length:        8 bytes

  23. Concurrency Level:      1000

  24. Time taken for tests:   2.878 seconds

  25. Complete requests:      1000

  26. Failed requests:        0

  27. Write errors:           0

  28. Total transferred:      202000 bytes

  29. HTML transferred:       8000 bytes

  30. Requests per second:    347.47 [#/sec] (mean) ##看这里!!!

  31. Time per request:       2877.963 [ms] (mean)

  32. Time per request:       2.878 [ms] (mean, across all concurrent requests)

  33. Transfer rate:          68.54 [Kbytes/sec] received

  34. Connection Times (ms)

  35.              min  mean[+/-sd] median   max

  36. Connect:        0  279 441.2      0    1001

  37. Processing:     1  580 545.3    303    1858

  38. Waiting:        0  579 545.3    302    1858

  39. Total:         44  859 905.7    362    2858

  40. Percentage of the requests served within a certain time (ms)

  41.  50%    362

  42.  66%    606

  43.  75%   1059

  44.  80%   1284

  45.  90%   2701

  46.  95%   2789

  47.  98%   2827

  48.  99%   2842

  49. 100%   2858 (longest request)

可以看到默认情况下,吞吐率为347.47 [#/sec]

结果,默认情况下 django和tornado吞吐率方面几乎是没区别的。

二、django、tornado最基本代码模拟访问数据库测试对比

最基本测试,直接使用项目本身启动程序,即python xxx.py形式 不使用任何转发。模拟数据库访问 这里使用加一段ping代码来进行。(机器不行就不要真的搞个mysql访问了。抱歉抱歉。)

django

 
   
   
 
  1. #这里根据上面的而是代码修改

  2. #!/usr/bin/env python

  3. #-*- coding:utf-8 -*-

  4. from django.shortcuts import render

  5. from django.template.context import RequestContext

  6. import os

  7. from django.http import HttpResponse

  8. def index(request):

  9.    os.system("ping -c 1 www.baidu.com") #增加个这个代码,咱们ping 1次百度来模拟这里进行了数据库select访问。

  10.    return HttpResponse("Hello world ! ")

 
   
   
 
  1. [root@centos1 untitled1]# python manage.py runserver 127.0.0.1:8888

  2. Performing system checks...

  3. System check identified no issues (0 silenced).

  4. September 18, 2017 - 07:09:00

  5. Django version 1.8.3, using settings 'untitled1.settings'

  6. Starting development server at http://127.0.0.1:8888/

  7. Quit the server with CONTROL-C.

  8. [root@centos1 ~]# ab -n 1000 -c 1000 http://127.0.0.1:8888/index/

  9. This is ApacheBench, Version 2.3 <$Revision: 655654 $>

  10. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/

  11. Licensed to The Apache Software Foundation, http://www.apache.org/

  12. Benchmarking 127.0.0.1 (be patient)

  13. Completed 100 requests

  14. Completed 200 requests

  15. Completed 300 requests

  16. Completed 400 requests

  17. Completed 500 requests

  18. Completed 600 requests

  19. Completed 700 requests

  20. Completed 800 requests

  21. Completed 900 requests

  22. Completed 1000 requests

  23. Finished 1000 requests

  24. Server Software:        WSGIServer/0.1

  25. Server Hostname:        127.0.0.1

  26. Server Port:            8888

  27. Document Path:          /index/

  28. Document Length:        14 bytes

  29. Concurrency Level:      1000

  30. Time taken for tests:   29.218 seconds

  31. Complete requests:      1000

  32. Failed requests:        0

  33. Write errors:           0

  34. Total transferred:      177000 bytes

  35. HTML transferred:       14000 bytes

  36. Requests per second:    34.23 [#/sec] (mean) ##看这里!!!

  37. Time per request:       29217.821 [ms] (mean)

  38. Time per request:       29.218 [ms] (mean, across all concurrent requests)

  39. Transfer rate:          5.92 [Kbytes/sec] received

  40. Connection Times (ms)

  41.              min  mean[+/-sd] median   max

  42. Connect:        0  680 2661.3      0   15001

  43. Processing:    29 1555 3123.2    412   13510

  44. Waiting:       28 1548 3124.4    403   13509

  45. Total:         31 2235 4130.7    434   17915

  46. Percentage of the requests served within a certain time (ms)

  47.  50%    434

  48.  66%    514

  49.  75%    726

  50.  80%   1526

  51.  90%  10198

  52.  95%  10465

  53.  98%  15329

  54.  99%  17629

  55. 100%  17915 (longest request)

可以看到这种情况下,吞吐率为34.23 [#/sec] 明显下降了很多

tornado

 
   
   
 
  1. import textwrap

  2. import tornado.httpserver

  3. import tornado.ioloop

  4. import tornado.options

  5. import tornado.web

  6. import os

  7. from tornado.options import define, options

  8. define("port", default=8888, help="run on the given port", type=int)

  9. class SyncHandler(tornado.web.RequestHandler):

  10.    def get(self, *args, **kwargs):

  11.        os.system("ping -c 1 www.baidu.com")

  12.        self.finish('hello word')

  13. if __name__ == "__main__":

  14.    tornado.options.parse_command_line()

  15.    app = tornado.web.Application(

  16.        handlers=[

  17.            (r"/index", SyncHandler)

  18.        ],

  19.        #debug = True,

  20.    )

  21.    http_server = tornado.httpserver.HTTPServer(app)

  22.    http_server.listen(options.port)

  23.    tornado.ioloop.IOLoop.instance().start()

 
   
   
 
  1. [root@centos1 ~]# ab -n 1000 -c 1000 http://127.0.0.1:8888/index

  2. This is ApacheBench, Version 2.3 <$Revision: 655654 $>

  3. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/

  4. Licensed to The Apache Software Foundation, http://www.apache.org/

  5. Benchmarking 127.0.0.1 (be patient)

  6. apr_socket_recv: Connection reset by peer (104)

  7. Total of 45 requests completed

  8. [root@centos1 ~]# ab -n 1000 -c 1000 http://127.0.0.1:8888/index

  9. This is ApacheBench, Version 2.3 <$Revision: 655654 $>

  10. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/

  11. Licensed to The Apache Software Foundation, http://www.apache.org/

  12. Benchmarking 127.0.0.1 (be patient)

  13. apr_poll: The timeout specified has expired (70007)

  14. ###由于tornado框架的设计理念问题。这种阻塞的请求方式无法完成本次测试。

  15. #在多次调低了参数之后 终于成功了一次

  16. ab -n 500 -c 500 http://127.0.0.1:8888/index。。。

  17. ab -n 200 -c 200 http://127.0.0.1:8888/index。。。

  18. ab -n 100 -c 100 http://127.0.0.1:8888/index。。。

  19. [root@centos1 ~]# ab -n 100 -c 100 http://127.0.0.1:8888/index

  20. This is ApacheBench, Version 2.3 <$Revision: 655654 $>

  21. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/

  22. Licensed to The Apache Software Foundation, http://www.apache.org/

  23. Benchmarking 127.0.0.1 (be patient).....done

  24. Server Software:        TornadoServer/4.5.2

  25. Server Hostname:        127.0.0.1

  26. Server Port:            8888

  27. Document Path:          /index

  28. Document Length:        8 bytes

  29. Concurrency Level:      100

  30. Time taken for tests:   23.339 seconds

  31. Complete requests:      100

  32. Failed requests:        0

  33. Write errors:           0

  34. Total transferred:      20200 bytes

  35. HTML transferred:       800 bytes

  36. Requests per second:    4.28 [#/sec] (mean) ##看这里看这里

  37. Time per request:       23338.514 [ms] (mean)

  38. Time per request:       233.385 [ms] (mean, across all concurrent requests)

  39. Transfer rate:          0.85 [Kbytes/sec] received

  40. Connection Times (ms)

  41.              min  mean[+/-sd] median   max

  42. Connect:        1    6   1.1      6       9

  43. Processing:    33 13564 10476.5  21515   23290

  44. Waiting:       33 13564 10476.5  21515   23289

  45. Total:         39 13570 10476.6  21522   23295

  46. Percentage of the requests served within a certain time (ms)

  47.  50%  21522

  48.  66%  22118

  49.  75%  22405

  50.  80%  22568

  51.  90%  22954

  52.  95%  23143

  53.  98%  23255

  54.  99%  23295

  55. 100%  23295 (longest request)

可以看到这种情况下,吞吐率为4.28 [#/sec] 惨不忍睹!

结果,很显然这个对比是没有意义的,由于tornado的单线程的设计逻辑,导致在不使用非阻塞是方法编程时性能简直惨不忍睹。(ps:由于这里是模拟了数据库访问操作,在实际的环境中访问mysql的速度理论上远大于ping 1次的速度)

限于篇幅关系,我们下一篇将继续进行django和tornado的性能测试。


以上是关于一篇关于django,tornado性能测试的非专业性报告的主要内容,如果未能解决你的问题,请参考以下文章

Tornado x MVC

Django/Flask/Tornado三大web框架性能分析

python tornado异步性能测试

关于性能测试并发的设置,看这一篇就够了

使用Tornado作为Django App的服务器

tornado 入门篇