`
ahuaxuan
  • 浏览: 633345 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

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

阅读更多
/**
*作者:张荣华
*日期: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模式有如下几个重要参数:
 protocol=PROTOCOL    fcgi, scgi, ajp, ... (default fcgi)
  host=HOSTNAME        hostname to listen on..
  port=PORTNUM         port to listen on.
  socket=FILE          UNIX socket to listen on.
  method=IMPL          prefork or threaded (default prefork)
  maxrequests=NUMBER   number of requests a child handles before it is 
                       killed and a new child is forked (0 = no limit).
  maxspare=NUMBER      max number of spare processes / threads
  minspare=NUMBER      min number of spare processes / threads.
  maxchildren=NUMBER   hard limit number of processes / threads
  daemonize=BOOL       whether to detach from terminal.
  pidfile=FILE         write the spawned process-id to this file.
  workdir=DIRECTORY    change to this directory when daemonizing.
  outlog=FILE          write stdout to this file.
  errlog=FILE          write stderr to this file.
  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

请求数    并发数   总时间
5000    50     22.86s
5000    25     23.37s
5000    10     23.37s
5000    100    21.58s


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

Time taken for tests:   7.883 seconds

Complete requests:      5000

Failed requests:        0

Write errors:           0

Total transferred:      5505084 bytes

HTML transferred:       4685937 bytes

Requests per second:    634.28 [#/sec] (mean)

Time per request:       78.830 [ms] (mean)

Time per request:       1.577 [ms] (mean, across all concurrent requests)

Transfer rate:          681.98 [Kbytes/sec] received


5000    25     7.545s
Concurrency Level:      25

Time taken for tests:   7.859 seconds

Complete requests:      5000

Failed requests:        0

Write errors:           0

Total transferred:      5504770 bytes

HTML transferred:       4685000 bytes

Requests per second:    636.20 [#/sec] (mean)

Time per request:       39.296 [ms] (mean)

Time per request:       1.572 [ms] (mean, across all concurrent requests)

Transfer rate:          684.01 [Kbytes/sec] received


5000    10     7.481s
Concurrency Level:      10

Time taken for tests:   7.920 seconds

Complete requests:      5000

Failed requests:        0

Write errors:           0

Total transferred:      5503153 bytes

HTML transferred:       4685000 bytes

Requests per second:    631.28 [#/sec] (mean)

Time per request:       15.841 [ms] (mean)

Time per request:       1.584 [ms] (mean, across all concurrent requests)

Transfer rate:          678.52 [Kbytes/sec] received


5000    100    7.776s
Concurrency Level:      100

Time taken for tests:   7.776 seconds

Complete requests:      5000

Failed requests:        0

Write errors:           0

Total transferred:      5504370 bytes

HTML transferred:       4685937 bytes

Requests per second:    643.04 [#/sec] (mean)

Time per request:       155.511 [ms] (mean)

Time per request:       1.555 [ms] (mean, across all concurrent requests)

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
Concurrency Level:      50

Time taken for tests:   22.676 seconds

Complete requests:      5000

Failed requests:        15

   (Connect: 0, Receive: 0, Length: 15, Exceptions: 0)

Write errors:           0

Non-2xx responses:      15

Total transferred:      5519788 bytes

HTML transferred:       4676480 bytes

Requests per second:    220.50 [#/sec] (mean)

Time per request:       226.762 [ms] (mean)

Time per request:       4.535 [ms] (mean, across all concurrent requests)

Transfer rate:          237.71 [Kbytes/sec] received


5000    25     25 s
Concurrency Level:      25

Time taken for tests:   25.330 seconds

Complete requests:      5000

Failed requests:        15

   (Connect: 0, Receive: 0, Length: 15, Exceptions: 0)

Write errors:           0

Non-2xx responses:      15

Total transferred:      5481652 bytes

HTML transferred:       4676480 bytes

Requests per second:    197.40 [#/sec] (mean)

Time per request:       126.649 [ms] (mean)

Time per request:       5.066 [ms] (mean, across all concurrent requests)

Transfer rate:          211.34 [Kbytes/sec] received


5000    10     15 s
Concurrency Level:      10

Time taken for tests:   15.463 seconds

Complete requests:      5000

Failed requests:        9

   (Connect: 0, Receive: 0, Length: 9, Exceptions: 0)

Write errors:           0

Non-2xx responses:      9

Total transferred:      5536528 bytes

HTML transferred:       4679888 bytes

Requests per second:    323.35 [#/sec] (mean)

Time per request:       30.926 [ms] (mean)

Time per request:       3.093 [ms] (mean, across all concurrent requests)

Transfer rate:          349.66 [Kbytes/sec] received


5000    100    21 s
Concurrency Level:      100

Time taken for tests:   21.225 seconds

Complete requests:      5000

Failed requests:        15

   (Connect: 0, Receive: 0, Length: 15, Exceptions: 0)

Write errors:           0

Non-2xx responses:      15

Total transferred:      5541355 bytes

HTML transferred:       4676480 bytes

Requests per second:    235.57 [#/sec] (mean)

Time per request:       424.498 [ms] (mean)

Time per request:       4.245 [ms] (mean, across all concurrent requests)

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
第一次:
Concurrency Level:      100

Time taken for tests:   9.682 seconds

Complete requests:      5000

Failed requests:        0

Write errors:           0

Total transferred:      5557585 bytes

HTML transferred:       4685000 bytes

Requests per second:    516.42 [#/sec] (mean)

Time per request:       193.642 [ms] (mean)

Time per request:       1.936 [ms] (mean, across all concurrent requests)

Transfer rate:          560.55 [Kbytes/sec] received

第二次
Concurrency Level:      100

Time taken for tests:   5.134 seconds

Complete requests:      5000

Failed requests:        0

Write errors:           0

Total transferred:      5560000 bytes

HTML transferred:       4685000 bytes

Requests per second:    973.84 [#/sec] (mean)

Time per request:       102.686 [ms] (mean)

Time per request:       1.027 [ms] (mean, across all concurrent requests)

Transfer rate:          1057.53 [Kbytes/sec] received


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

Concurrency Level:      25

Time taken for tests:   5.347 seconds

Complete requests:      5000

Failed requests:        0

Write errors:           0

Total transferred:      5559748 bytes

HTML transferred:       4685000 bytes

Requests per second:    935.07 [#/sec] (mean)

Time per request:       26.736 [ms] (mean)

Time per request:       1.069 [ms] (mean, across all concurrent requests)

Transfer rate:          1015.38 [Kbytes/sec] received

5000    10     8.78s

Concurrency Level:      10

Time taken for tests:   5.723 seconds

Complete requests:      5000

Failed requests:        0

Write errors:           0

Total transferred:      5562916 bytes

HTML transferred:       4687811 bytes

Requests per second:    873.64 [#/sec] (mean)

Time per request:       11.446 [ms] (mean)

Time per request:       1.145 [ms] (mean, across all concurrent requests)

Transfer rate:          949.22 [Kbytes/sec] received

5000    50    7.90s
Concurrency Level:      50

Time taken for tests:   5.239 seconds

Complete requests:      5000

Failed requests:        0

Write errors:           0

Total transferred:      5560923 bytes

HTML transferred:       4685937 bytes

Requests per second:    954.43 [#/sec] (mean)

Time per request:       52.387 [ms] (mean)

Time per request:       1.048 [ms] (mean, across all concurrent requests)

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下认为线程模型更快的同学有所帮助。
分享到:
评论
44 楼 daxiong921 2009-10-07  
???????????666
43 楼 bohemia 2008-12-25  
引用
定期监测Python进程内存占用,一旦超过限额,杀掉重起。


有点暴力. 呵呵.
如果系统正在处理某些关键业务,被Kill后的结果可能会出现不可预知的问题了.
42 楼 robbin 2008-12-18  
引用
可惜的是PythonVM,在Win下,暂时没资源的上限设置; 跑久了,内存就一直在高位了.


这个到简单,写个监控shell脚本,定期监测Python进程内存占用,一旦超过限额,杀掉重起。

事实上你目前的方式也是需要python进程定期重起的,只不过是根据进程处理的请求数,达到一个请求数,就杀掉重起了。这还不如我根据内存限额来决定是否需要杀掉重起来的合理。
41 楼 bohemia 2008-12-18  
robbin 写道
bohemia 写道
robbin 写道
ahuaxuan 写道
robbin 写道

我部署JavaEye服务器是自己写shell脚本来控制FCGI进程的spawn,respawn,很稳定,很健壮,而且很容易维护。

想了几分钟,还是没有想通具体的做法或者思路是什么样子的,shell脚本是如何去控制系统中进程的行为的呢,难道那个进程有提供这样的接口或者什么滴?

知识不够用了,robbin大哥能否为我们讲解一下具体的思路。


我们是静态spawn的,用lighttpd的spawn-fcgi命令来spawn进程就可以了,不进行动态spawn,当然shell启动脚本还有很多其他工作要做。另外的一个shell脚本用来监控FCGI的内存使用状况,发现超过限额以后就respawn它,另外还有一个进程健康检查的shell,如果发现进程crash掉,就spawn一个新的进程。


这样感觉是一个饭馆,只要开张,只有10张桌子, 如果客人真的来多了,也就真的没办法服务了.
不知道有没有更好的办法,即能解决服务器的稳定服务,又能提供动态的扩展?


软件上动态的扩展不是很难的事情,但问题是你软件进行了动态扩展,你的硬件也能跟上吗? 如果你硬件不能动态跟上,就意味着更大的灾难。

就好比饭馆就那么大点地方,你摆了10张桌子,客人坐满了,新来的客人还是不要再进来的好,这就是静态spawn,至少能够保证进来的客人有饭吃,能服务的好。

你非要动态spawn,客人来几个,你就加几张桌子,结果摆了100张桌子,所有客人都坐得不舒服,吃不到饭,你觉得这样更好?

Robbin的意思我理解;

这样处理是更合理的一种方式,软件在单台服务器上的服务上限必须加以限定;如果硬件需要扩展,可以采用负载均衡等方法扩展; 这样至少可以保证单台服务器的正常服务.

所以JVM有内存限定,要应用服务器有线程限定,应用程序有并发用户数限定.

可惜的是PythonVM,在Win下,暂时没资源的上限设置; 跑久了,内存就一直在高位了.
40 楼 robbin 2008-12-14  
bohemia 写道
robbin 写道
ahuaxuan 写道
robbin 写道

我部署JavaEye服务器是自己写shell脚本来控制FCGI进程的spawn,respawn,很稳定,很健壮,而且很容易维护。

想了几分钟,还是没有想通具体的做法或者思路是什么样子的,shell脚本是如何去控制系统中进程的行为的呢,难道那个进程有提供这样的接口或者什么滴?

知识不够用了,robbin大哥能否为我们讲解一下具体的思路。


我们是静态spawn的,用lighttpd的spawn-fcgi命令来spawn进程就可以了,不进行动态spawn,当然shell启动脚本还有很多其他工作要做。另外的一个shell脚本用来监控FCGI的内存使用状况,发现超过限额以后就respawn它,另外还有一个进程健康检查的shell,如果发现进程crash掉,就spawn一个新的进程。


这样感觉是一个饭馆,只要开张,只有10张桌子, 如果客人真的来多了,也就真的没办法服务了.
不知道有没有更好的办法,即能解决服务器的稳定服务,又能提供动态的扩展?


软件上动态的扩展不是很难的事情,但问题是你软件进行了动态扩展,你的硬件也能跟上吗? 如果你硬件不能动态跟上,就意味着更大的灾难。

就好比饭馆就那么大点地方,你摆了10张桌子,客人坐满了,新来的客人还是不要再进来的好,这就是静态spawn,至少能够保证进来的客人有饭吃,能服务的好。

你非要动态spawn,客人来几个,你就加几张桌子,结果摆了100张桌子,所有客人都坐得不舒服,吃不到饭,你觉得这样更好?
39 楼 bohemia 2008-12-13  
robbin 写道
ahuaxuan 写道
robbin 写道

我部署JavaEye服务器是自己写shell脚本来控制FCGI进程的spawn,respawn,很稳定,很健壮,而且很容易维护。

想了几分钟,还是没有想通具体的做法或者思路是什么样子的,shell脚本是如何去控制系统中进程的行为的呢,难道那个进程有提供这样的接口或者什么滴?

知识不够用了,robbin大哥能否为我们讲解一下具体的思路。


我们是静态spawn的,用lighttpd的spawn-fcgi命令来spawn进程就可以了,不进行动态spawn,当然shell启动脚本还有很多其他工作要做。另外的一个shell脚本用来监控FCGI的内存使用状况,发现超过限额以后就respawn它,另外还有一个进程健康检查的shell,如果发现进程crash掉,就spawn一个新的进程。


这样感觉是一个饭馆,只要开张,只有10张桌子, 如果客人真的来多了,也就真的没办法服务了.
不知道有没有更好的办法,即能解决服务器的稳定服务,又能提供动态的扩展?
38 楼 ahuaxuan 2008-12-10  
ray_linn 写道
PS: 我再多嘴问一句:

AB和django是在两台机上,还是在一台机器上? 如果是一台机器,那你的数据应该就有问题了。AB应该也是多线程来模拟多用户的,可能会对多线程模型造成影响。


I know for realistic benchmarks you shouldn't run it on the same server.

这个应该没有什么关系,我测线程模型的时候cpu根本就没有能得到充分的利用.大概70-80%,所以不会有什么影响,而且ab的多线程对django的多线程根本不在同一个进程内,何来影响之说呀
37 楼 ray_linn 2008-12-10  
PS: 我再多嘴问一句:

AB和django是在两台机上,还是在一台机器上? 如果是一台机器,那你的数据应该就有问题了。AB应该也是多线程来模拟多用户的,可能会对多线程模型造成影响。


I know for realistic benchmarks you shouldn't run it on the same server.
36 楼 ahuaxuan 2008-12-10  
ray_linn 写道

我觉得首先还是应该问问他们的测试环境和测试方法,光看测试结果没有任何意义。

学过工科的,大概都学过测量学吧?


我还真没有学过测量学,不过文章开头的那两个地址的测试都太单薄了,没有环境,没有参数,啥都没有结论就出来.

我的测试结果我在前面的帖子里就说明了,在linux kernel2.6且机器多核的场景下得到的结论,如果按你所说,soloris,mac,windos都测一遍其实意义不大.甚至什么人去关心这种事情.


所以要指出我的结论是错误的,前提也应该是在linux kernel2.6,机器是多核的前提下
35 楼 ray_linn 2008-12-10  
ahuaxuan 写道
做测试的原因是为了严谨一点,君不见网上n多的文章都说线程模型快,他们既没有测全面,也没有分析全面,误导大众.我只是想还进程模型一个清白,呵呵


我觉得首先还是应该问问他们的测试环境和测试方法,光看测试结果没有任何意义。

学过工科的,大概都学过测量学吧?
34 楼 ray_linn 2008-12-10  
ahuaxuan 写道

不过我很奇怪的是,在windows下多线程真的可以使用多核吗,人家内部人事都说了,windows对多cpu支持比较差,你应该知道一点吧



理论上来说,我觉得这应该没问题的,完全取决于内核如何调配CPU资源的问题。多线程的模式不单单是MS一家,许多比MS更优秀的OS/2(NT核心), MAC OS都是采用thread而不是进程的方式。这个内部人士难道不知道他的公司里几乎都是windows服务器么?

linux下的线程说到底就是个“仿真线程”进程,也就无怪呼慢了,NTPL我猜想是利用了"kernel thread"--(强烈鄙视这个混淆视听的名字)进程来提高效率,但从kernel看出来的话,到底还是进程。至于2.4上,如果开启的是linuxThread,那慢也是自然的。

所以我想首先请你确认一下用的是NTPL还是linuxthread,其次我想说的,linux上的thread不是真的thread,比较起来意义也不大。


你要测试线程的话,不喜欢windows也可以用Sun Solaris,我只是举一个典型的线程核心的os,robbin非要牵扯出对windows的讨伐,呵呵。

我们可以姑且认为solaris和linux的os效率接近,那么在两个os上比较一下django的performance吧。
33 楼 ahuaxuan 2008-12-10  
ray_linn 写道

我奇怪的是你这一段"两个核心可以”同时“控制不同的进程。而线程模型下是单进程的,有一个核就被浪费了"...如何被浪费了?

之前我的理解是错误的,误认为线程模型下,没有完全使用多核的优势,这个错误的理解robbin大哥已经指出了啊.

ray_linn 写道

俺这一段的主旨是想说内核里运行的是啥,就该用啥.linux下就该用进程,windows下就该用线程,无须费老大力气去做测试.

做测试的原因是为了严谨一点,君不见网上n多的文章都说线程模型快,他们既没有测全面,也没有分析全面,误导大众.我只是想还进程模型一个清白,呵呵

-------------------------------------------------

不过我很奇怪的是,在windows下多线程真的可以使用多核吗,人家内部人事都说了,windows对多cpu支持比较差,你应该知道一点吧
32 楼 ray_linn 2008-12-09  
ahuaxuan 写道
ray_linn 写道
终于找到点东西了:

“NPTL uses a similar approach to LinuxThreads, in that the primary abstraction known by the kernel is still a process, and new threads are created with the clone() system call (called from the NPTL library). ”


总来来说内核决定了一切,该是进程还是进程,该是线程还是线程。

大锅,俺没有看出来你的这个引用有说明什么特殊的问题.

这段引用只是在描述NPTL和linuxthreads这两个模块产生的线程对内核来说其他都是进程.没有什么实质性的说明啊.

有人说"2.4内核的多线程无法使用多个cpu,一个进程的线程都被限制在同一个cpu上运行",不过我的内核是2.6的,而且我并没有说我出现一个核被使用,另外一个核没有被使用的情况.由此可见,在2.6内核中多线程是可以使用多个cpu的,但是正如robbin大哥所说,由于全局锁的问题,导致其并不能完全充分的使用这两个核



我奇怪的是你这一段"两个核心可以”同时“控制不同的进程。而线程模型下是单进程的,有一个核就被浪费了"...如何被浪费了?


俺这一段的主旨是想说内核里运行的是啥,就该用啥.linux下就该用进程,windows下就该用线程,无须费老大力气去做测试.
31 楼 robbin 2008-12-09  
Windows操作系统在多CPU服务器上面的表现不佳,而且可以说是非常糟糕!这是我在HP公司,以及Dell公司从事服务器产品线咨询的两位朋友先后告诉我的情况。我那位Dell的朋友甚至告诉我,他们有些客户碰到的问题,必须向微软公司索要某些特定的Windows内核补丁,才能恢复正常。(有些问题微软公司会告诉说新补丁还没有出,那就只好继续忍受)

BTW: 其实我很奇怪的是,你在Dell公司的哪个部门工作,如果你是负责服务器产品线的,这些问题你怎么会都不知道?如果是公司内部的IT部门,那我就理解了。
30 楼 ahuaxuan 2008-12-09  
ray_linn 写道
终于找到点东西了:

“NPTL uses a similar approach to LinuxThreads, in that the primary abstraction known by the kernel is still a process, and new threads are created with the clone() system call (called from the NPTL library). ”


总来来说内核决定了一切,该是进程还是进程,该是线程还是线程。

大锅,俺没有看出来你的这个引用有说明什么特殊的问题.

这段引用只是在描述NPTL和linuxthreads这两个模块产生的线程对内核来说其他都是进程.没有什么实质性的说明啊.

有人说"2.4内核的多线程无法使用多个cpu,一个进程的线程都被限制在同一个cpu上运行",不过我的内核是2.6的,而且我并没有说我出现一个核被使用,另外一个核没有被使用的情况.由此可见,在2.6内核中多线程是可以使用多个cpu的,但是正如robbin大哥所说,由于全局锁的问题,导致其并不能完全充分的使用这两个核
29 楼 ray_linn 2008-12-09  
终于找到点东西了:

“NPTL uses a similar approach to LinuxThreads, in that the primary abstraction known by the kernel is still a process, and new threads are created with the clone() system call (called from the NPTL library). ”


总来来说内核决定了一切,该是进程还是进程,该是线程还是线程。
28 楼 ray_linn 2008-12-09  
二者设计差别很大,很大原因我个人觉得是GUI与非GUI的区别,导致了进程调度还是线程调度的设计差别。

Linux线程象是个补丁硬打进内核里,至于线程如何被调度,如何利用CPU,找了许多资料也没发现出个所以然来,所以也无从了解为啥linux的线程要比windows慢这么多,但是总得看来,linux下的线程模型毛病不少,不完全符合POSIX,包括最新的NPTL。

我个人经验在windows下使用PLINQ多线程的时候,不会出现你那种一个CPU满,一个CPU闲的状态,如果真要比较线程和进程,我建议把线程模型的danjo部署到windows上,而不是linux上。
27 楼 ahuaxuan 2008-12-09  
ray_linn 写道
ahuaxuan 写道

由此可见,对于多核的cpu下,进程模型明显更占优势,因为在多核的情况下,两个核心可以”同时“控制不同的进程。而线程模型下是单进程的,有一个核就被浪费了。


这点肯定不是放之四海皆准的。

Linux内核以进程调度为主,但是Windows的内核里却只有线程调度没有进程调度,进程只是个容器而已。你可以把你的测试挪到windows下看看。

linux 2.4的线程模型是很糟糕的,甚至整个linux的线程模型都是糟糕的,比windows下的线程模型要慢上许多。例如 Windows XP CriticalSection API要比 Linux pthread 互斥锁快 2 倍。



windows不怎么熟悉,我那个结论是针对linux的,之前看了深入理解linux内核这本书的进程部分,所以觉得在linux下,这个结论应该还是正确的.

26 楼 ray_linn 2008-12-09  
ahuaxuan 写道

由此可见,对于多核的cpu下,进程模型明显更占优势,因为在多核的情况下,两个核心可以”同时“控制不同的进程。而线程模型下是单进程的,有一个核就被浪费了。


这点肯定不是放之四海皆准的。

Linux内核以进程调度为主,但是Windows的内核里却只有线程调度没有进程调度,进程只是个容器而已。你可以把你的测试挪到windows下看看。

linux 2.4的线程模型是很糟糕的,甚至整个linux的线程模型都是糟糕的,比windows下的线程模型要慢上许多。例如 Windows XP CriticalSection API要比 Linux pthread 互斥锁快 2 倍。


25 楼 robbin 2008-12-08  
ahuaxuan 写道
robbin 写道
现在低端的PC服务器动辄都双四核了,你想,这8个cpu内核的服务器,你不用多进程,不是傻子嘛。

嗯,明白.

而且发现大多数公司现在都有的一个问题,就是一个tomcat下部署多个app,其实是所有的app都部署在一个tomcat下,完全没有安装机器的特点和进程模型与线程模型的特点来考量是否需要发挥机器的最大性能.


如果说需要发挥机器的性能,尤其是cpu密集型应用,应该是部署多个tomcat,每个tomcat一个进程,这样才能更好的利用机器,才能充分发挥机器的性能.


没错,我在JavaEye建议过很多次的。现代的服务器硬件发展水平,单JVM进程已经无法充分利用硬件资源了,必须做垂直群集,更何况Java的垂直群集还有负载均衡,故障转移,高容错性等等好处。

相关推荐

Global site tag (gtag.js) - Google Analytics