论坛首页 编程语言技术论坛

PHP框架的繁荣是正确的发展方向吗?

浏览 246926 次
该帖已经被评为精华帖
作者 正文
   发表时间:2009-01-26   最后修改:2009-01-26
呵呵,一直在潜水关注这个帖子,看到前面 robbin 提出 PHP 的运行模型跟 Ruby、Python 和 Java 的差异,以为很多 PHP 开发者(包括框架开发者)会有所感悟,然而一路看下来却没有看到有谁能真正认识到这个本质区别给 PHP 开发带来的影响,所以想出来说几句。

必须重点强调的问题是:PHP 的运行模型与 Python 运行模型到底有何差异?这种差异对 PHP 开发和 Python 开发到底有什么影响?

看看这两个图(如果线条不对齐,可以拷贝下来使用等宽字体来看):

PHP 工作进程的运行环境(o为通常意义上的对象):

             | | FastCGI 端口
             | |
+------------+ +--------------+
|       FastCGI  SAPI         | PHP 自带的 SAPI
+----------+------------------+
|  o    o  |  o o o o o o o   |
| PHP Core |  Zend  Engine    |
|    o     |    o o o o o o   |
+-↓-+-↓-+-↓-+-↓-+-↓-+-↓-+
| 已 | 已 | 已 |o当o| 未 | 未 |
| 执 | 执 | 执 |o前o| 来 | 来 |
| 行 | 行 | 行 |o请o| 执 | 执 |
| 过 | 过 | 过 |o求o| 行 | 行 |
| 的 | 的 | 的 |o执o| 的 | 的 | 框架,比如 Symfony
| 请 | 请 | 请 |o行o| 请 | 请 |
| 求 | 求 | 求 |o环o| 求 | 求 |
|    |    |    |o境o|    |    |
|    |    |    |oooo|    |    |
+----+----+----+----+----+----+
|        o o o o o o o        |
|         Extensions          |
|         o o o o o o         |
+-----------------------------+


Python 工作进程的运行环境(o为通常意义上的对象):


             | | FastCGI 端口
             | |
+------------+ +-------------+\
|  o o o o FastCGI o o o o   | \
+----------------------------+-/ 比如Flup实现
| o o o  WSGI Server  o o o  |/
+---↓---↓---↓---↓---↓---+
|                            |
|          o o o o           |
|           o o o            |
|      WSGI Application      | 比如 Django
|          o o o o           |
|         o o o o o          |
|                            |
+----------------------------+
|        o o o o o o         |
|      Python Libraries      |
|         o o o o o          |
+----------------------------+



由上面的图示可以看出,PHP 进程本身就实现了所谓的“PHP 框架”!这跟 Python 进程是绝对不同的!
也因为这些本质的差别,造成 PHP 脚本无法实现进程内跨请求存在的变量。

使用 PHP 编写的“PHP 框架”,再怎么折腾,也绕不开 Zend Engine 虚拟机创建出来的“请求执行环境”。而 Python 框架是正宗的 Web 框架。为什么这么说?因为你可以用 Python 脚本操纵 Python 进程内的所有实体。君不见,《PoEAA》、《设计模式》、《Core J2EE Patterns》等书里面总结和提炼出来的模式,都是针对持久进程运行模型的,而不是 PHP 这种运行模型,可惜能真正认识到这点的 PHP 开发者寥寥无几。因此,PHP 框架再怎么写,再怎么抄,终究也是东施效颦:Front Controller 是持久的,PHP 做不到,目前 PHP 框架里的“Front Controller”只抄对了形,没抄对神,再怎么折腾,可怜的它在请求结束后一样灰飞烟灭;Router 并不是 PHP 的概念,同样是持久型进程的概念;至于 ORM ,就更不用说了,Python、Ruby、Java 之类的 ORM 都是常驻内存的持久型对象,PHP 不是,每次请求一过来,它就必须加载整个 ORM,折腾好后,请求结束时就 over,下一个请求再来,再加载,再 over ……

当然 PHP 的这种模型也有非常好的优点,就是它彻底杜绝了内存和资源泄露,PHP 程序员再怎么菜,也极难写出有内存泄露的程序:请求一结束,所有的泄露都被回收。

至于这两种模型的性能怎样?请各位去测试测试,呵呵。

以上随手写的,本来是打算写进我的一篇“论文”里的,只是看着帖子手痒,没办法:)

另外,不当之处欢迎拍砖!
1 请登录后投票
   发表时间:2009-01-26  
dualface 写道
koda 写道
dualface 写道

PHP 框架另一个令人诟病的地方就是性能问题,几乎让人认为 : PHP + 框架 = 性能差。
但造成这种问题的根源根本不是 PHP 或者框架,而是这些 PHP 框架设计和实现造成的,drupal 为什么慢也是这个原因。


既然是框架实现的问题,那为了实现Java、ROR等WEB框架同等或者近似的丰富功能,有什么已经存在的PHP框架证明其性能超过、等同或者接近这些框架的性能?

另外,PHP本身的运行机制没有制约它的框架或者应用的性能吗(不加特殊的优化机制如APC等)?



Java、RoR 我并不熟悉,所以没有做过性能测试。但是 PHP 框架的性能问题并不是 PHP 语言本身造成的。就像 Java 一样可以做出很慢的框架和很快的框架,同一种语言下不同的设计和实现会导致差异很大的结果。节后希望能够做一个更全面点的性能测试,到时候还希望熟悉 Java、RoR 的朋友提供帮助。

单纯从语言角度看,PHP 比 Ruby 快很多,这一点是毋庸置疑的。而 Lighttpd + FastCGI + PHP 的性能也很出色,再配合 APC 等 opcode cache 和数据库持久连接,能够把 bootstarp 的成本降到最低。如果加上 memcached,还可以进一步提高性能。

至于你说不用 APC,我想没必要这样比,因为 APC 本就是 PHP 的一个扩展,可以轻松添加到 PHP 运行环境中。难道你的 Rails 应用不会借助 memcached 来提高性能么?


实际上你得承认,PHP解释器的实现方式制约了 PHP 框架的编写,这其中的制约是否会影响性能,还有待挖掘。

另外,语言是没有快慢之分的,只有语言的实现(编译器,解释器)有快慢的区别。

在 PHP 里,默认 opcode 不是随进程持久的,而是跟请求一样的生命周期,也就是说请求一过来,PHP 解释器编译所有的代码,生成 opcode,然后 Zend 虚拟机执行 opcode。请求结束后,opcode 也自动销毁。因此,PHP 可以实现一改代码无需重启进程就能看到效果。opcode cache (比如 APC,eAccelerator,XCache)所做的,只是把 opcode 缓存在进程的内存空间里,避免了每个请求都编译一次代码带来的开销。

反之,在 Python 里,opcode 默认就是跟进程具有相同的生命周期,因此 python 也就无所谓 opcode cache。这样也造成了 Python 的 Web 应用程序在改过代码后,必须重启进程的烦恼。

加上了 opcode cache 的 PHP 进程,需要一种事件机制来判断脚本是否被修改,否则 cache 过期,就无法实现一改代码就能生效的效果了。
0 请登录后投票
   发表时间:2009-01-26  
哟,Qee的老大来啦,先顶
0 请登录后投票
   发表时间:2009-01-26  
引用

由上面的图示可以看出,PHP 进程本身就实现了所谓的“PHP 框架”!这跟 Python 进程是绝对不同的!
也因为这些本质的差别,造成 PHP 脚本无法实现进程内跨请求存在的变量。

使用 PHP 编写的“PHP 框架”,再怎么折腾,也绕不开 Zend Engine 虚拟机创建出来的“请求执行环境”。而 Python 框架是正宗的 Web 框架。为什么这么说?因为你可以用 Python 脚本操纵 Python 进程内的所有实体。君不见,《PoEAA》、《设计模式》、《Core J2EE Patterns》等书里面总结和提炼出来的模式,都是针对持久进程运行模型的,而不是 PHP 这种运行模型,可惜能真正认识到这点的 PHP 开发者寥寥无几。


运行模式的区别,有经验的 PHP 开发者都很清楚。你说寥寥无几,实在是太片面了。

至于《PoEAA》和《设计模式》,我没看到几个模式是必须要求持久进程运行模型的。
而 Core J2EE Patterns 我没看过,但是既然是针对 Java 领域的,不适合 PHP 很正常。

引用

因此,PHP 框架再怎么写,再怎么抄,终究也是东施效颦:Front Controller 是持久的,PHP 做不到,目前 PHP 框架里的“Front Controller”只抄对了形,没抄对神,再怎么折腾,可怜的它在请求结束后一样灰飞烟灭;


请问 Front Controller 的作用是什么?

我不知道你心目中的 Front Controller 是什么。但绝大部分框架中,Front Controller 的作用很简单:响应所有的请求,然后分发这些请求。对于 Front Controller 来说,是不是常驻内存并不是必须的,难道不能常驻内存就不能分发请求?

引用

Router 并不是 PHP 的概念,同样是持久型进程的概念;


如果我没理解错误的话,你说的 Router 应该是大多数框架中那种 Router。Router 的作用通常是将特定格式的 URL 地址解析为一组参数,从而让 Front Controller 决定如何分发请求。这样的 Router 和持久型进程有什么关系呢?


引用

至于 ORM ,就更不用说了,Python、Ruby、Java 之类的 ORM 都是常驻内存的持久型对象,PHP 不是,每次请求一过来,它就必须加载整个 ORM,折腾好后,请求结束时就 over,下一个请求再来,再加载,再 over ……


ORM 是在关系式数据库中维护对象和对象间的关系。我不知道你说的“整个ORM”是指什么,如果只是单单指“提供 ORM 服务”的这一层,那么完全可以实现得很快很轻量。但如果你说的“整个 ORM”是指“ORM 服务和被 ORM 管理的对象”,那我只能说你还需要再学习。

换个角度看,不管是不是持久型进程模型,如果单独看每一个请求。每个请求用到的对象数量都是很有限的,并不需要把应用程序的整个对象体系载入到内存中。这种情况下,如果有一个快速、轻量的 ORM 服务,实现一个具有可用价值的 ORM 又有什么不行的呢。

PHP 的运行模型当然有很显著的缺陷,但并不是不可以弥补的。配合 APC 或其他 opcode cache,实现跨请求的对象完全可以,而且速度非常快,mediawiki 就是如此。如果再配合 memcached,ORM 也可以获得理想的性能。

1 请登录后投票
   发表时间:2009-01-26  
diogin 写道
dualface 写道
koda 写道
dualface 写道

PHP 框架另一个令人诟病的地方就是性能问题,几乎让人认为 : PHP + 框架 = 性能差。
但造成这种问题的根源根本不是 PHP 或者框架,而是这些 PHP 框架设计和实现造成的,drupal 为什么慢也是这个原因。


既然是框架实现的问题,那为了实现Java、ROR等WEB框架同等或者近似的丰富功能,有什么已经存在的PHP框架证明其性能超过、等同或者接近这些框架的性能?

另外,PHP本身的运行机制没有制约它的框架或者应用的性能吗(不加特殊的优化机制如APC等)?



Java、RoR 我并不熟悉,所以没有做过性能测试。但是 PHP 框架的性能问题并不是 PHP 语言本身造成的。就像 Java 一样可以做出很慢的框架和很快的框架,同一种语言下不同的设计和实现会导致差异很大的结果。节后希望能够做一个更全面点的性能测试,到时候还希望熟悉 Java、RoR 的朋友提供帮助。

单纯从语言角度看,PHP 比 Ruby 快很多,这一点是毋庸置疑的。而 Lighttpd + FastCGI + PHP 的性能也很出色,再配合 APC 等 opcode cache 和数据库持久连接,能够把 bootstarp 的成本降到最低。如果加上 memcached,还可以进一步提高性能。

至于你说不用 APC,我想没必要这样比,因为 APC 本就是 PHP 的一个扩展,可以轻松添加到 PHP 运行环境中。难道你的 Rails 应用不会借助 memcached 来提高性能么?


实际上你得承认,PHP解释器的实现方式制约了 PHP 框架的编写,这其中的制约是否会影响性能,还有待挖掘。

另外,语言是没有快慢之分的,只有语言的实现(编译器,解释器)有快慢的区别。

在 PHP 里,默认 opcode 不是随进程持久的,而是跟请求一样的生命周期,也就是说请求一过来,PHP 解释器编译所有的代码,生成 opcode,然后 Zend 虚拟机执行 opcode。请求结束后,opcode 也自动销毁。因此,PHP 可以实现一改代码无需重启进程就能看到效果。opcode cache (比如 APC,eAccelerator,XCache)所做的,只是把 opcode 缓存在进程的内存空间里,避免了每个请求都编译一次代码带来的开销。

反之,在 Python 里,opcode 默认就是跟进程具有相同的生命周期,因此 python 也就无所谓 opcode cache。这样也造成了 Python 的 Web 应用程序在改过代码后,必须重启进程的烦恼。

加上了 opcode cache 的 PHP 进程,需要一种事件机制来判断脚本是否被修改,否则 cache 过期,就无法实现一改代码就能生效的效果了。



PHP 解释器的实现方式当然为框架的实现带来了限制,但是反过来简单的运行模型也大大简化了框架的设计和实现。

至于语言的快慢,确实是我说得不准确。

最后关于 opcode cache 的问题,我想不是根本性问题。而且即便启用了 opcode cache,修改 .php 文件后还是可以立即生效的。

0 请登录后投票
   发表时间:2009-01-28   最后修改:2009-01-28
python可以reload 模块,而无需重启整个进程,不过在复杂的模块依赖情况下,重启整个进程会更好些
0 请登录后投票
   发表时间:2009-01-28   最后修改:2009-01-28
dualface 写道
如果再配合 memcached,ORM 也可以获得理想的性能。


memcached和PHP架构没有什么必然联系。不适合放在一起说。

即使memcached作为PHP方案的一部分,多了个这样的非PHP框架的东西,不管怎样,都会带来各方面成本的增加,因为之前总有人强调开发的高效性,我想这个开发高效应该包含调试和维护高效的,多一个环节,肯定是会增加调试成本的。所以讨论方案的时候,既要获得memcached高性能的好处,又保持PHP结构的简洁性,这样是不太好的。
0 请登录后投票
   发表时间:2009-01-28  
icewubin 写道
dualface 写道
如果再配合 memcached,ORM 也可以获得理想的性能。


memcached和PHP架构没有什么必然联系。不适合放在一起说。

即使memcached作为PHP方案的一部分,多了个这样的非PHP框架的东西,不管怎样,都会带来各方面成本的增加,因为之前总有人强调开发的高效性,我想这个开发高效应该包含调试和维护高效的,多一个环节,肯定是会增加调试成本的。所以讨论方案的时候,既要获得memcached高性能的好处,又保持PHP结构的简洁性,这样是不太好的。


memcached 当然和 PHP 架构没有必然联系,但是 memcached 现在就是一种事实标准,稍微有点规模的 Web 应用在基础架构中都会用到。PHP 框架对 memcached 提供全面的支持是必须的。

而且我在前面的回复中提到 memcached,是指 PHP 框架配合 memcached,可以为应用程序提供理想的性能表现。不代表 PHP 框架就一定要用 memcached。所以你的理解是有问题的。


此外,将 memcached 加入到 PHP 架构中,并不存在你所说的增加成本的问题,更不会影响开发的高效性。因为基于 PHP 框架开发的应用程序,对各种缓存(包括 memcached)的使用都是通过一个统一的接口。因此使用不同的缓存服务,对应用程序来说是透明的。

最后,如果不用 memcached,PHP 框架的 ORM 就一定比其他框架更慢?
难道其他框架的 ORM 就可以在没有 memcached 支持的情况下,避免频繁查询对象时对数据库的操作?

0 请登录后投票
   发表时间:2009-01-28   最后修改:2009-01-28
dualface 写道
memcached 当然和 PHP 架构没有必然联系,但是 memcached 现在就是一种事实标准,稍微有点规模的 Web 应用在基础架构中都会用到。PHP 框架对 memcached 提供全面的支持是必须的。

而且我在前面的回复中提到 memcached,是指 PHP 框架配合 memcached,可以为应用程序提供理想的性能表现。不代表 PHP 框架就一定要用 memcached。所以你的理解是有问题的。


此外,将 memcached 加入到 PHP 架构中,并不存在你所说的增加成本的问题,更不会影响开发的高效性。因为基于 PHP 框架开发的应用程序,对各种缓存(包括 memcached)的使用都是通过一个统一的接口。因此使用不同的缓存服务,对应用程序来说是透明的。

最后,如果不用 memcached,PHP 框架的 ORM 就一定比其他框架更慢?
难道其他框架的 ORM 就可以在没有 memcached 支持的情况下,避免频繁查询对象时对数据库的操作?


我感觉你没有明白我的意思,或者说,我请问你想说明什么?

是不是说PHP的web框架比python的web框架开发效率(包括多人协作的调试和维护效率)高?还是指其他。

1.“PHP 框架对 memcached 提供全面的支持”?
  是不是可以理解为PHP框架为memcached服务?如果仅仅讨论框架,为何把memcached算进来?其他框架不也可以用memcached么?难道说你的意思是指,你认为PHP调用memcached的功能比其他框架更方便么?

2.我还没有明白你为什么要提到“PHP 框架配合 memcached”?和本帖讨论有必然联系么?

3.我特地说了这里的成本包括调试和维护成本,不如再加个多人协作和学习成本好了。
  照你的逻辑,是不是任何框架都“使用都是通过一个统一的接口、且对应用程序来说是透明的”,则该框架就不会影响开发的高效性么?如果是的话,用他个10-100个框架好了。

4.你说的最后一段才是大家关心的,您大可发挥,但别牵涉到memcached。
  如果你说的是疑问句,我就回答,当然有办法,不就是缓存么?memcached不过是个缓存结构而已,世界上只有memcached这一个缓存框架么?
0 请登录后投票
   发表时间:2009-01-28   最后修改:2009-01-28
引用

我感觉你没有明白我的意思,或者说,我请问你想说明什么?

是不是说PHP的web框架比python的web框架开发效率(包括多人协作的调试和维护效率)高?还是指其他。

1.“PHP 框架对 memcached 提供全面的支持”?
  是不是可以理解为PHP框架为memcached服务?如果仅仅讨论框架,为何把memcached算进来?其他框架不也可以用memcached么?难道说你的意思是指,你认为PHP调用memcached的功能比其他框架更方便么?

2.我还没有明白你为什么要提到“PHP 框架配合 memcached”?和本帖讨论有必然联系么?

3.我特地说了这里的成本包括调试和维护成本,不如再加个多人协作和学习成本好了。
  照你的逻辑,是不是任何框架都“使用都是通过一个统一的接口、且对应用程序来说是透明的”,则该框架就不会影响开发的高效性么?如果是的话,用他个10-100个框架好了。



前面有朋友说 PHP 的开发框架性能不好,我说这不代表所有 PHP 框架的性能都不好。但我也没有说 PHP 框架就一定比其他语言的框架更快。

然后还有朋友说 PHP 不适合实现 ORM,而我反对这种看法。这时,我提到了 memcached,意思是 PHP 框架不但可以 ORM,而且配合 memcached 还可以获得理想的性能。我并没有把 PHP 框架和 memcached 放到一起来说,显然只是你自己这么想的而已。

关于第3点,我也不认同你的意见。不过最好单独开贴来说,不然跑题太远。

引用


引用

最后,如果不用 memcached,PHP 框架的 ORM 就一定比其他框架更慢?
难道其他框架的 ORM 就可以在没有 memcached 支持的情况下,避免频繁查询对象时对数据库的操作?


4.你说的最后一段才是大家关心的,您大可发挥,但别牵涉到memcached。
如果你说的是疑问句,我就回答,当然有办法,不就是缓存么?memcached不过是个缓存结构而已,世界上只有memcached这一个缓存框架么?


我不知道你是否是对 PHP 有成见,即便我又提到 memcached,也用不着说什么“大可发挥”之类的话吧?

至于 memcached 缓存框架?没听过这种说法。不过我这里再次提到 memcached 是因为 PHP 本身对 memcached 有相应的扩展,用起来很方便。难道有现成的常用缓存服务不用,非要搞个不常用的?

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

关于 memcached 的问题希望就此打住,因为实在是跑题太远了。我再强调一次“提到 memcached 是因为这个缓存服务可以为 PHP 的 ORM 带来性能提升”。但并不等于没了 memcached,PHP 的 ORM 就玩不转。

最后,PHP 的 ORM 性能和其他语言框架的 ORM 相比,性能是高是低,我没有测试数据,所以我不能下结论。但是反过来,既然你也没有测试数据,也请不要轻易下结论。

0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics