`

django,性能测试,以及对fastcgi下进程模型和线程模型的分析

 
阅读更多

转自:http://www.iteye.com/topic/267429

 

 

 

 

/** 
*作者:张荣华 
*日期:2008-11-15 
**/ 

之前网上有很多关于django的测试,他们的测试结果都表明django在fastcgi模式下,使用线程模型要比进程模型快,而且更稳定,具体文章见: 
http://irobot.blog.hexun.com/20332312_d.html 
http://taoyh163.blog.163.com/blog/static/19580356200802433559850/ 
但是ahuaxuan根据操作系统的原理判断结果不应该是这样,理论上来讲,进程应该更快。为了证明自己的观点,于是做了以下测试。 

那么在讲解我的测试方法之前,按照惯例,现来讲以下dango中fastcgi模式的一些知识点。 
dango的fastcgi模式有如下几个重要参数: 

Java代码  收藏代码
  1. protocol=PROTOCOL    fcgi, scgi, ajp, ... (default fcgi)  
  2.  host=HOSTNAME        hostname to listen on..  
  3.  port=PORTNUM         port to listen on.  
  4.  socket=FILE          UNIX socket to listen on.  
  5.  method=IMPL          prefork or threaded (default prefork)  
  6.  maxrequests=NUMBER   number of requests a child handles before it is   
  7.                       killed and a new child is forked (0 = no limit).  
  8.  maxspare=NUMBER      max number of spare processes / threads  
  9.  minspare=NUMBER      min number of spare processes / threads.  
  10.  maxchildren=NUMBER   hard limit number of processes / threads  
  11.  daemonize=BOOL       whether to detach from terminal.  
  12.  pidfile=FILE         write the spawned process-id to this file.  
  13.  workdir=DIRECTORY    change to this directory when daemonizing.  
  14.  outlog=FILE          write stdout to this file.  
  15.  errlog=FILE          write stderr to this file.  
  16.  umask=UMASK          umask to use when daemonizing (default 022).  



相信做java的同学一看就比较明白了,很多参数和tomcat中是一样的,主要有一个host,port,socket需要讲解一下,host和port我们知道应该是成对出现的,那么socket是什么呢,其实他们都是socket,只不过,host+port模式是tcp sock,而socket是unix sock,他们都是套接字,一个是操作系统本地的,一个是网络套接字而已。 

我的测试工具是apachbench,简称ab,在apache的bin目录中有这个工具。我的web服务器是lighttpd1.4。 
我一共划分了4个场景,第一个场景是操作数据库的请求,第二个场景是请求缓存的场景,而且使用线程模型,第3和第4个场景都是fastcgi的进程模型。 

场景一 
涉及到查数据库的url,每次请求一条简单的sql语句。 
python manage.py runfcgi method=threaded host=127.0.0.1 port=3033 daemonize=false 

请求数    并发数   总时间 

Java代码  收藏代码
  1. 5000    50     22.86s  
  2. 5000    25     23.37s  
  3. 5000    10     23.37s  
  4. 5000    100    21.58s  



场景二 
不涉及到数据的url,执行一段判断后返回(可以认为数据都放在缓存中)。 
python manage.py runfcgi method=threaded host=127.0.0.1 port=3033 
请求数    并发数   总时间 
5000    50     7.734s 

Java代码  收藏代码
  1. Concurrency Level:      50  
  2.   
  3. Time taken for tests:   7.883 seconds  
  4.   
  5. Complete requests:      5000  
  6.   
  7. Failed requests:        0  
  8.   
  9. Write errors:           0  
  10.   
  11. Total transferred:      5505084 bytes  
  12.   
  13. HTML transferred:       4685937 bytes  
  14.   
  15. Requests per second:    634.28 [#/sec] (mean)  
  16.   
  17. Time per request:       78.830 [ms] (mean)  
  18.   
  19. Time per request:       1.577 [ms] (mean, across all concurrent requests)  
  20.   
  21. Transfer rate:          681.98 [Kbytes/sec] received  



5000    25     7.545s 

Java代码  收藏代码
  1. Concurrency Level:      25  
  2.   
  3. Time taken for tests:   7.859 seconds  
  4.   
  5. Complete requests:      5000  
  6.   
  7. Failed requests:        0  
  8.   
  9. Write errors:           0  
  10.   
  11. Total transferred:      5504770 bytes  
  12.   
  13. HTML transferred:       4685000 bytes  
  14.   
  15. Requests per second:    636.20 [#/sec] (mean)  
  16.   
  17. Time per request:       39.296 [ms] (mean)  
  18.   
  19. Time per request:       1.572 [ms] (mean, across all concurrent requests)  
  20.   
  21. Transfer rate:          684.01 [Kbytes/sec] received  



5000    10     7.481s 

Java代码  收藏代码
  1. Concurrency Level:      10  
  2.   
  3. Time taken for tests:   7.920 seconds  
  4.   
  5. Complete requests:      5000  
  6.   
  7. Failed requests:        0  
  8.   
  9. Write errors:           0  
  10.   
  11. Total transferred:      5503153 bytes  
  12.   
  13. HTML transferred:       4685000 bytes  
  14.   
  15. Requests per second:    631.28 [#/sec] (mean)  
  16.   
  17. Time per request:       15.841 [ms] (mean)  
  18.   
  19. Time per request:       1.584 [ms] (mean, across all concurrent requests)  
  20.   
  21. Transfer rate:          678.52 [Kbytes/sec] received  



5000    100    7.776s 

Java代码  收藏代码
  1. Concurrency Level:      100  
  2.   
  3. Time taken for tests:   7.776 seconds  
  4.   
  5. Complete requests:      5000  
  6.   
  7. Failed requests:        0  
  8.   
  9. Write errors:           0  
  10.   
  11. Total transferred:      5504370 bytes  
  12.   
  13. HTML transferred:       4685937 bytes  
  14.   
  15. Requests per second:    643.04 [#/sec] (mean)  
  16.   
  17. Time per request:       155.511 [ms] (mean)  
  18.   
  19. Time per request:       1.555 [ms] (mean, across all concurrent requests)  
  20.   
  21. Transfer rate:          691.32 [Kbytes/sec] received  


场景一和场景 二对比可以发现,带有数据操作的请求明显需要更多的时间,之间从缓存中拿数据,每秒中fastcgi可以处理1000个请求。 

场景三 
不涉及到数据的url,执行一段判断后返回(可以认为数据都放在缓存中)。使用进程模型。 
python manage.py runfcgi method=prefork host=127.0.0.1 port=3033 
请求数    并发数   总时间 
5000    50     22 s 

Java代码  收藏代码
  1. Concurrency Level:      50  
  2.   
  3. Time taken for tests:   22.676 seconds  
  4.   
  5. Complete requests:      5000  
  6.   
  7. Failed requests:        15  
  8.   
  9.    (Connect: 0, Receive: 0, Length: 15, Exceptions: 0)  
  10.   
  11. Write errors:           0  
  12.   
  13. Non-2xx responses:      15  
  14.   
  15. Total transferred:      5519788 bytes  
  16.   
  17. HTML transferred:       4676480 bytes  
  18.   
  19. Requests per second:    220.50 [#/sec] (mean)  
  20.   
  21. Time per request:       226.762 [ms] (mean)  
  22.   
  23. Time per request:       4.535 [ms] (mean, across all concurrent requests)  
  24.   
  25. Transfer rate:          237.71 [Kbytes/sec] received  


5000    25     25 s 

Java代码  收藏代码
  1. Concurrency Level:      25  
  2.   
  3. Time taken for tests:   25.330 seconds  
  4.   
  5. Complete requests:      5000  
  6.   
  7. Failed requests:        15  
  8.   
  9.    (Connect: 0, Receive: 0, Length: 15, Exceptions: 0)  
  10.   
  11. Write errors:           0  
  12.   
  13. Non-2xx responses:      15  
  14.   
  15. Total transferred:      5481652 bytes  
  16.   
  17. HTML transferred:       4676480 bytes  
  18.   
  19. Requests per second:    197.40 [#/sec] (mean)  
  20.   
  21. Time per request:       126.649 [ms] (mean)  
  22.   
  23. Time per request:       5.066 [ms] (mean, across all concurrent requests)  
  24.   
  25. Transfer rate:          211.34 [Kbytes/sec] received  



5000    10     15 s 

Java代码  收藏代码
  1. Concurrency Level:      10  
  2.   
  3. Time taken for tests:   15.463 seconds  
  4.   
  5. Complete requests:      5000  
  6.   
  7. Failed requests:        9  
  8.   
  9.    (Connect: 0, Receive: 0, Length: 9, Exceptions: 0)  
  10.   
  11. Write errors:           0  
  12.   
  13. Non-2xx responses:      9  
  14.   
  15. Total transferred:      5536528 bytes  
  16.   
  17. HTML transferred:       4679888 bytes  
  18.   
  19. Requests per second:    323.35 [#/sec] (mean)  
  20.   
  21. Time per request:       30.926 [ms] (mean)  
  22.   
  23. Time per request:       3.093 [ms] (mean, across all concurrent requests)  
  24.   
  25. Transfer rate:          349.66 [Kbytes/sec] received  



5000    100    21 s 

Java代码  收藏代码
  1. Concurrency Level:      100  
  2.   
  3. Time taken for tests:   21.225 seconds  
  4.   
  5. Complete requests:      5000  
  6.   
  7. Failed requests:        15  
  8.   
  9.    (Connect: 0, Receive: 0, Length: 15, Exceptions: 0)  
  10.   
  11. Write errors:           0  
  12.   
  13. Non-2xx responses:      15  
  14.   
  15. Total transferred:      5541355 bytes  
  16.   
  17. HTML transferred:       4676480 bytes  
  18.   
  19. Requests per second:    235.57 [#/sec] (mean)  
  20.   
  21. Time per request:       424.498 [ms] (mean)  
  22.   
  23. Time per request:       4.245 [ms] (mean, across all concurrent requests)  
  24.   
  25. Transfer rate:          254.96 [Kbytes/sec] received  


通过场景二和三的对比,我们可以看出线程模型在默认情况下比进程模型更加快。不过根据操作系统的特性,ahuaxuan认为事有蹊跷。理论上来讲,在速度方面,进程模型不应该比线程模型慢,虽然网上有的文章确实有提到线程模型比进程模型快,不过ahuaxuan觉得他们的测试是有问题的。在研究了django的fastcgi参数之后,再根据做java的经验我发现问题可能出现在进程的创建上。于是调整参数,继续测试。 


场景四 
不涉及到数据的url,执行一段判断后返回(可以认为数据都放在缓存中)。将最大进程数和最小进程数调整到50。 
python manage.py runfcgi method=prefork host=127.0.0.1 port=3033 daemonize=false minspare=50 maxspare=50 
请求数    并发数   总时间 
5000    100     8.16s 
第一次: 

Java代码  收藏代码
  1. Concurrency Level:      100  
  2.   
  3. Time taken for tests:   9.682 seconds  
  4.   
  5. Complete requests:      5000  
  6.   
  7. Failed requests:        0  
  8.   
  9. Write errors:           0  
  10.   
  11. Total transferred:      5557585 bytes  
  12.   
  13. HTML transferred:       4685000 bytes  
  14.   
  15. Requests per second:    516.42 [#/sec] (mean)  
  16.   
  17. Time per request:       193.642 [ms] (mean)  
  18.   
  19. Time per request:       1.936 [ms] (mean, across all concurrent requests)  
  20.   
  21. Transfer rate:          560.55 [Kbytes/sec] received  


第二次 

Java代码  收藏代码
  1. Concurrency Level:      100  
  2.   
  3. Time taken for tests:   5.134 seconds  
  4.   
  5. Complete requests:      5000  
  6.   
  7. Failed requests:        0  
  8.   
  9. Write errors:           0  
  10.   
  11. Total transferred:      5560000 bytes  
  12.   
  13. HTML transferred:       4685000 bytes  
  14.   
  15. Requests per second:    973.84 [#/sec] (mean)  
  16.   
  17. Time per request:       102.686 [ms] (mean)  
  18.   
  19. Time per request:       1.027 [ms] (mean, across all concurrent requests)  
  20.   
  21. Transfer rate:          1057.53 [Kbytes/sec] received  



分析,一模一样的两次请求,为什么差两倍的速度呢,根据ahuaxuan的分析,问题应该出在进程的创建上,第二次测试,由于进程已经存在,所以速度非常的快,比线程模型快了2倍不到一点。 
5000    25     8.90s 

Java代码  收藏代码
  1. Concurrency Level:      25  
  2.   
  3. Time taken for tests:   5.347 seconds  
  4.   
  5. Complete requests:      5000  
  6.   
  7. Failed requests:        0  
  8.   
  9. Write errors:           0  
  10.   
  11. Total transferred:      5559748 bytes  
  12.   
  13. HTML transferred:       4685000 bytes  
  14.   
  15. Requests per second:    935.07 [#/sec] (mean)  
  16.   
  17. Time per request:       26.736 [ms] (mean)  
  18.   
  19. Time per request:       1.069 [ms] (mean, across all concurrent requests)  
  20.   
  21. Transfer rate:          1015.38 [Kbytes/sec] received  


5000    10     8.78s 

Java代码  收藏代码
  1. Concurrency Level:      10  
  2.   
  3. Time taken for tests:   5.723 seconds  
  4.   
  5. Complete requests:      5000  
  6.   
  7. Failed requests:        0  
  8.   
  9. Write errors:           0  
  10.   
  11. Total transferred:      5562916 bytes  
  12.   
  13. HTML transferred:       4687811 bytes  
  14.   
  15. Requests per second:    873.64 [#/sec] (mean)  
  16.   
  17. Time per request:       11.446 [ms] (mean)  
  18.   
  19. Time per request:       1.145 [ms] (mean, across all concurrent requests)  
  20.   
  21. Transfer rate:          949.22 [Kbytes/sec] received  


5000    50    7.90s 

Java代码  收藏代码
  1. Concurrency Level:      50  
  2.   
  3. Time taken for tests:   5.239 seconds  
  4.   
  5. Complete requests:      5000  
  6.   
  7. Failed requests:        0  
  8.   
  9. Write errors:           0  
  10.   
  11. Total transferred:      5560923 bytes  
  12.   
  13. HTML transferred:       4685937 bytes  
  14.   
  15. Requests per second:    954.43 [#/sec] (mean)  
  16.   
  17. Time per request:       52.387 [ms] (mean)  
  18.   
  19. Time per request:       1.048 [ms] (mean, across all concurrent requests)  
  20.   
  21. Transfer rate:          1036.63 [Kbytes/sec] received  



对比场景三和场景四发现,在进程模式下在没有指定maxspare和minspare值的情况下,由于每次并发大的时候都动态的去创建进程,效率明显下降,5000个请求居然需要20s之多。而一旦设置了maxspare和minspare之后,只有第一次请求的时候,需要创建进程,之后经常已经存在,不需要创建,也不需要动态的消亡(maxspare和minspare值太小会导致fastcgi父进程频繁的创建和销毁子进程,非常的消耗cpu),整个应用程序的处理能力大大提高。 

再对比场景二和场景四,可以发现不管是进程模式还是线程模式,每秒都能处理超过1000次的请求。而且在并发较大的情况下,进程模式效率更高。由此可见在网站访问量巨大的情况下,使用进程模型才是比较好的选择,而不是网上所说的使用线程模型。 

后来为了作对比,ahuaxuan在线程模型上也加了maxspare=50,minspare=50,不过性能和没有加几乎一样,可见,这两个参数对进程模型的影响比较大。而且也可以进一步说明操作系统创建进程消耗确实大。 

从这个对比结果,我们还可以得知: 
1线程创建在ubuntu中的代价比进程小的多。(根据观察,在创建进程的时候,cpu上升到100%,而线程模型的cpu只有80%的样子) 
2在进程已经存在的情况下,处理请求的能力,进程要比线程能力强。而且要强出1/3左右的样子 

最后,贴出我的机器配置 
cpu:t8100 
内存:2g 
硬盘:5400转的希捷 

希望本文能够给对django性能有怀疑,以及对fastcgi下认为线程模型更快的同学有所帮助。 

分享到:
评论

相关推荐

    Python-使用PythonDjango的Web自动化测试平台

    2. **模型测试**:在Django中,模型是数据结构的定义,测试模型通常包括验证数据的有效性、查询行为以及与数据库的交互。我们可以创建测试类来覆盖这些测试点,确保模型的正确性。 3. **视图测试**:视图是处理HTTP...

    2023年Django大二下学期期末复习

    在2023年的大二下学期,Django框架的学习成为了重要的课程内容,这门期末复习资料涵盖了Django的核心概念、关键技术和实际应用。Django是Python编程语言中的一款高级Web开发框架,它以“快速开发、清晰设计、强调可...

    Python-Django模型字段加密解密您的数据并加密保存至数据库中

    本文将深入探讨如何在Django中实现模型字段的加密和解密,以及如何利用luojilab-django-mirage-field-5d96836这样的库来简化这个过程。 首先,理解Django模型字段。在Django中,模型是数据库表的面向对象表示。每个...

    浅析Django处理流程和结构分析django.doc

    Django 框架处理流程和结构分析 Django 是一个高级 Python Web 框架,鼓励快速开发和干净的、MVC 设计。它包括一个模板系统、对象相关的映射和用于动态创建管理界面的框架。支持 ORM、Cache、i18n、Admin 等众多...

    8. Django 表单与模型

    本文将深入探讨Django中的表单(Forms)和模型(Models),以及它们如何协同工作来构建高效、安全的Web应用。 ### Django模型(Models) **1. 模型的概念** Django模型是数据库交互的主要接口,它定义了数据库表...

    Python-动态创建一个模型的多个tablename并通过DjangoORM操作

    默认情况下,Django会根据模型类的名字来生成数据库表名,但可以通过`Meta`类中的`db_table`属性自定义表名。 在Django中动态创建模型并设置不同表名,我们需要创建一个基类,然后通过继承该基类来创建不同的模型。...

    python的Django框架模型

    Python的Django框架模型是Django的核心组成部分之一,它提供了数据模型的设计和数据库交互的能力。在Django中,模型(Model)是用来描述数据库结构的Python类,它定义了数据库表的字段、类型以及各种关系。下面我们...

    Django(三)模型与数据库

    除了基本操作,Django的模型还支持更高级的功能,如表关联(如一对一、一对多、多对多关系)、字段的默认值、自定义校验规则、序列化等。此外,还可以通过模型定义复杂的查询,如过滤、排序、分组和聚合。 在实际...

    基于Django构建在线文本分类预测系统代码、模型、数据集:SVM模型在线预测与部署 基于 Django 3.2 框架

    基于Django构建在线文本分类预测系统代码、模型、数据集:SVM模型在线预测与部署 基于 Django 3.2 框架,参考博客:https://blog.csdn.net/wangyaninglm/article/details/116334297

    django部署配置以及nginx配置

    这会启动一个主进程和4个工作进程,每个进程有2个线程,监听本地8000端口,并使用指定的Django项目目录和wsgi入口。 文件"配置步骤.txt"应该包含详细的部署步骤,大致可能包括以下内容: 1. 安装Nginx和uWSGI。 2. ...

    django-performance-testing:通过自动化测试对Django进行性能测试!

    3. **监控和报告(Monitoring & Reporting)**:收集性能数据,生成详细的报告,以便分析和决策。 **使用方法** 要开始使用"django-performance-testing",首先需要安装该库,这可以通过`pip install django-...

    Django数据传输测试

    需要注意的是,在实际开发过程中,还需要考虑安全性、性能优化、前端交互以及后端逻辑的复杂性等多个方面的问题。本例仅提供了一个基础的入门示例,用于引导初学者搭建一个最简单的Django数据传输应用。

    Django入门与实践教程1

    【第一个单元测试】章节介绍了Django的测试框架,教导读者编写测试用例,确保代码的质量和稳定性。测试驱动开发是现代Web开发的最佳实践。 【静态文件设置】和【Django Admin介绍】章节分别讲解如何处理项目的静态...

    基于django垃圾邮件分类多种模型在线部署页面展示源码+说明文档.zip

    基于django垃圾邮件分类多种模型在线部署页面展示源码+说明文档.zip基于django垃圾邮件分类多种模型在线部署页面展示源码+说明文档.zip基于django垃圾邮件分类多种模型在线部署页面展示源码+说明文档.zip基于django...

    Django实现并发处理的例子

    在这个例子中,我们关注的是如何在Django项目中处理并发,特别是在Linux环境下,这涉及到多线程、锁机制以及资源管理等核心概念。 首先,"并发处理"是指系统在同一时间内处理多个请求的能力。在Django中,这可以...

    基于Django开发的智能分类图片平台源代码+数据库+测试集+模型

    测试集用于验证系统性能,确保分类的准确性和稳定性。而预训练模型是已经过训练的神经网络模型,它可能使用了如卷积神经网络(CNN)等深度学习技术来学习和理解图像特征,以进行分类任务。 “Django范文/模板/素材...

    基于Django和Vue的心脑血管疾病预测系统

    具体可以参考此界面...用现在的数据进行数据清洗和分析,然后采用机器学习算法训练模型,可以对数据输入数据进行预测 目前的数据集和相关特征字段 数据说明 有 3 种类型的输入特征:

    django笔记 django笔记

    Django是Python编程语言中的一款强大且流行的Web框架,它以“快速开发”和“约定优于配置”的理念为核心,让开发者能够高效地构建高质量的...通过深入学习和实践,开发者可以利用Django构建出复杂、高性能的Web应用。

    毕业设计:基于python django的自动化测试管理系统.zip

    1. 测试用例管理:创建、编辑、删除测试用例,以及分类和标签化,方便查找和组织。 2. 测试套件(Suite):将多个测试用例组合成一个测试套件,便于一次性执行一组相关的测试。 3. 测试执行:运行测试用例,记录测试...

    Django异步任务线程池实现原理

    通过以上知识点的详细介绍和实际代码示例,文章帮助开发者深入理解Django中异步任务线程池的实现原理,以及如何在实际项目中利用这些原理来提高程序的性能和响应速度。这对于提升大规模数据处理能力、优化用户体验...

Global site tag (gtag.js) - Google Analytics