我的一个应用程序中的某个页面在 Web 服务器上的运行速度与本地测试服务器相比非常慢。环境的某些根本差异可能解释了这个问题,但我希望找到一个比这更可行的解决方案。
服务器:
Solaris 10
Apache 2.2.9 Prefork
PHP 5.2.6
该服务器在 4 个不到一年的 Sun 机器集群上运行,性能方面应该不会有任何问题。
本地测试服务器:
Windows XP
Apache 2.2.14 WinNT
PHP 5.3.1
这实际上是我自己的桌面 - 一台不错的机器,但与 Sun 的机器相比就逊色多了。
该应用程序是用 CodeIgniter 编写的,我使用其中的分析功能将速度减慢的原因追溯到 Model::Model()。例如,Model::Model() 在本地运行时间为 0.0006 秒,在服务器上运行时间为 0.0045 秒。当您在页面上加载数百个模型时,这显然是一个问题。
我从 ServerFault 交叉发布了此内容,因为它可能与 CodeIgniter 更密切相关。
从本地加载页面需要 2-3 秒。从服务器加载则需要 11-15 秒。
本地模块,但不在远程:
- mod_actions
- mod_asis
- 复制代码
- mod_dav_lock
- mod_isapi mod_autoindex_color
远程模块,而非本地模块:
- 验证数据库模型
- mod_authn_anon
- 修改权限
- mod_authz_owner
- mod_cache
- 修改缓存
- mod_deflate
- 修改 LDAP 服务器
- mod_ldap
- mod_mime_magic
- mod_expires
- mod_unique_id
- mod_autoindex
- mod_suexec
- mod_userdir
- libphp5
- mod_dtrace
- mod_security2
编辑:
我将基准测试逐步向下、逐级进行,发现最大的差异在于这一段代码(位于 CodeIgniter 函数 Model::_assign_libraries 中,在模型的构造函数中被调用):
$time = microtime()*1000;
foreach (array_keys(get_object_vars($CI)) as $key)
{
if ( ! isset($this->$key) AND $key != $this->_parent_name)
{
// In some cases using references can cause
// problems so we'll conditionally use them
if ($use_reference == TRUE)
{
$this->$key = NULL; // Needed to prevent reference errors with some configurations
$this->$key =& $CI->$key;
}
else
{
$this->$key = $CI->$key;
}
}
}
if (get_class($this) == 'SeatType')
echo sprintf('%.5f ms|', (microtime()*1000 - $time));
在本地,每次迭代打印大约 0.48ms。在集群上,每次迭代打印大约 3.9ms。
我开始怀疑这个问题是否在 Apache/PHP 之外 - 我将 php.ini 和 htconf 文件复制到我的本地服务器,并且(在删除 mod_dtrace 之后,几乎没有其他内容),我确实看到了性能的提高。(上述检查现在在本地打印 .2ms。)
答案1
我假设您已经比较了 PHP/apache 设置和加载的模块?
你确定它是 Web 服务器/PHP 吗?我对 CI 不够熟悉,所以无法确定,但听起来模型会连接到数据库。
如果确实连接到数据库,请尝试检查
- 连接:网络延迟/吞吐量、主机名查找、持久连接、甚至并发问题(锁定)、防火墙中的连接速率限制……
- 数据库:反向 DNS 查找、连接速率限制、总体负载
答案2
我们发现,虽然 SPARC 服务器看起来应该比我的 PC 上的 core2 quad 性能更好,但它们完全是通过线程来实现的。任何单个线程实际上都会表现得更差。性能下降很可能就是因为这个原因。