在考虑HTTP(无状态协议)的情况下理解PHP/CGI性能


Understanding PHP/CGI performance considering HTTP (stateless protocol)

问题的一些背景

我刚刚浏览了moodle CMS中使用的一些*.php文件。Moodle使用PHP脚本生成动态发送给访问者的HTML页面的内容。通常会发生类似的情况("包含级联"):

// file: file1.php
require(file2.php);

//文件:file2.phprequire(file3.php);require(file4.php);

等等。。。

事实上,从请求的*.php文件开始,直到最终产生一些输出,都需要包含大量其他文件。即使这很有道理,我也很担心,因为它会影响速度/性能。似乎每次都有很多初始化被重做

问题

知道HTTP协议是一个无状态协议,在我看来,对于发送到服务器的每个请求,都有必要一遍又一遍地运行PHP/CGI代码中完成的所有可能的初始化。这是一个有效/真实的假设吗?

示例:我需要访问数据库,我想使用一些对象来安全地访问数据库,这些对象有助于完成所有这些"更安全"的准备语句/清理等操作。因此,用于此操作的对象是在我包含的文件(即myDatabaseAccessObject.php)中创建的。

关于这个例子,问题是:
由于HTTP是无状态的,因此没有机会在每次请求时重新完成设置(即解析)myDatabaseAccessObject.php的工作,这是否属实?

或者PHP是通过一种方式来缓存已经完成的工作?(如果是这样的话,是以透明的方式(即脚本作者可以告诉缓存什么)或模糊的方式完成的,php引擎会做一些不可见的缓存,对作者来说?)

是因为我对正在发生的事情有一个绝对有缺陷的看法,还是确实是一次又一次地完成了工作,如果在多个后续请求之间保存了PHP脚本所需的一些初始化,这些工作可以保存?

你完全是对的。所有数据库连接和其他初始化都是在每次执行PHP脚本时完成的。这正是因为HTTP协议的无状态性。

话虽如此,还是有办法加快这一进程的。PHP会话处理可以为您做一些事情(尽管它不能缓存连接),例如Smarty有一个不错的缓存和编译系统等。

好吧,首先:HTTP不再是真正的无状态。HTTP1.1添加了持久连接,这本身并没有使其成为有状态的,但也没有使协议完全成为无状态的。如果HTTP 1.1真的是无状态的,并且你会使用持久连接(分块传输),你会诅咒协议太慢,所以他们在某种程度上解决了这个问题,这就是为什么我听说HTTP 1.1被称为肮脏的无状态。这就是我要说的。

所以,回到你的问题:是的,PHP/CGI的标准安装(确定你没有使用fCGI?)必须解析、编译和执行每个请求的所有代码。这不是什么大不了的事,但它仍然是开销
你不能将状态保持在两个请求之间,不是真的。如果你仔细想想,这就是为什么许多人认为static关键字在PHP中毫无意义,但这是另一回事。

您的问题集中在数据库连接上。好吧,可以使用持久数据库连接,PHP可能会从连接池中提取下一个连接。但这是危险的、混乱的,只是一场等待发生的事故
连接数据库不太可能是您案例中的主要瓶颈。由于您使用moodle,我认为这将是过多的I/O操作(您所说的要求级联)。

通过缓存PHP在编译脚本时生成的实际字节码,可以很容易地避免这种情况。看看APC,AFAIK,它是使用中最流行的缓存扩展。它让您可以控制缓存的内容、方式和时间
如果你喜欢生活在边缘,而你没有在做一些关键的事情,你甚至可以检查一下,如果你把代码编译成一个可执行的,你会获得多大的性能提升