PHP factor 30 Linux与Windows的性能差异
我们的团队正在开发WordPress插件,并在两个独立的服务器上提供托管实例。我们的WordPress安装由Git管理,所有服务器都部署了相同的源和WordPress安装程序,只有数据库中的域和实际数据不同。对于每个安装,MySql都在同一台主机上运行。WordPress只在每台服务器上运行 然而,在Windows Server 2008 RC2上部署此设置后,我们注意到与其他服务器相比,性能有很大的差异:使用PHP生成的页面的生成时间从平均400ms增加到4000-5000ms。对于仅由Apache提供的静态资源,速度与linux上的大致相同 因此,我们采取了一些措施来缩小问题的范围:PHP factor 30 Linux与Windows的性能差异,php,linux,windows,wordpress,performance,Php,Linux,Windows,Wordpress,Performance,我们的团队正在开发WordPress插件,并在两个独立的服务器上提供托管实例。我们的WordPress安装由Git管理,所有服务器都部署了相同的源和WordPress安装程序,只有数据库中的域和实际数据不同。对于每个安装,MySql都在同一台主机上运行。WordPress只在每台服务器上运行 然而,在Windows Server 2008 RC2上部署此设置后,我们注意到与其他服务器相比,性能有很大的差异:使用PHP生成的页面的生成时间从平均400ms增加到4000-5000ms。对于仅由Apa
preg_match
)大约需要90毫秒,在Windows上需要3000毫秒
下面提供了分析、系统测试和配置详细信息我们不想优化这个脚本(我们确实知道怎么做)。我们希望让脚本在windows上运行的速度与在Linux上运行的速度大致相同(假定opcache/的设置相同)。也不需要优化脚本的内存占用
更新:一段时间后,系统似乎内存不足,引发内存不足异常和随机分配。有关更多详细信息,请参见下文。重新启动Apache/PHP暂时解决了这个问题
到\u get\u浏览器的跟踪是:
File (called from)
require wp-blog-header.php (index.php:17)
wp (wp-blog-header.php:14)
WP->main (functions.php:808)
php::do_action_ref_array (class-wp.php:616)
php::call_user_func_array (wp-includes/plugin:507)
wp_slimstat::slimtrack (php::internal (507))
wp_slimstat::_get_browser (wp-slimstat.php:385)
更新2:出于某种原因,我不记得我们在服务器上重新激活PHP作为Apache模块(同样的模块会带来糟糕的性能)。但今天,它们运行速度极快(~1秒/请求)。添加Opcache可将其降低到约400ms/req。Apache/PHP/Windows保持不变
1)分析结果
在所有机器上都使用XDebug进行了分析。通常我们只收集了几次运行—这些运行足以显示大部分时间(50%+)的位置:WordPress插件的方法[get_browser][1]
:
protected static function _get_browser(){
// Load cache
@include_once(plugin_dir_path( __FILE__ ).'databases/browscap.php');
// browscap.php contains $slimstat_patterns and $slimstat_browsers
$browser = array('browser' => 'Default Browser', 'version' => '1', 'platform' => 'unknown', 'css_version' => 1, 'type' => 1);
if (empty($slimstat_patterns) || !is_array($slimstat_patterns)) return $browser;
$user_agent = isset($_SERVER['HTTP_USER_AGENT'])?$_SERVER['HTTP_USER_AGENT']:'';
$search = array();
foreach ($slimstat_patterns as $key => $pattern){
if (preg_match($pattern . 'i', $user_agent)){
$search = $value = $search + $slimstat_browsers[$key];
while (array_key_exists(3, $value) && $value[3]) {
$value = $slimstat_browsers[$value[3]];
$search += $value;
}
break;
}
}
// Lots of other lines to relevant to the profiling results
}
此函数类似于PHP的get_browser
检测浏览器的功能和操作系统。大部分脚本执行时间都花在这个foreach
循环中,用于评估所有那些preg\u match
(每页请求大约8000-10000)。在Linux上大约需要90毫秒,在Windows上需要3000毫秒。所有测试设置的结果相同(图中显示了两次执行的数据):
当然,加载两个巨大的阵列需要一些时间。也计算正则表达式。但我们希望它们在Linux和Windows上所用的时间大致相同。这是linux vm上的评测结果(仅一页请求)。差别非常明显:
另一个时间杀手实际上是WordPress使用的对象缓存:
function get( $key, $group = 'default', $force = false, &$found = null ) {
if ( empty( $group ) )
$group = 'default';
if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) )
$key = $this->blog_prefix . $key;
if ( $this->_exists( $key, $group ) ) {
$found = true;
$this->cache_hits += 1;
if ( is_object($this->cache[$group][$key]) )
return clone $this->cache[$group][$key];
else
return $this->cache[$group][$key];
}
$found = false;
$this->cache_misses += 1;
return false;
}
此函数本身花费的时间(3次脚本执行):
在linux上:
最后一个真正的杀手是翻译。在WordPress中,从内存加载的每个翻译需要0.2ms到4ms的时间:
在linux上:
2)经过测试的系统
为了确保虚拟化或Apache确实会影响这一点,我们在几个设置上对此进行了测试。已在所有设置上禁用了抗病毒:
- Linux Debian、Apache2和PHP的最新稳定版本。对于在虚拟机中运行的开发人员来说,这与对于临时/实时服务器来说是一样的。作为期望性能的参考系统。要么在我们的办公室里运行,要么在一些托管提供的地方运行(共享空间)。Windows系统有4GB到8GB的RAM,内存使用率一直低于50%。虚拟化永远不会同时运行Windows和Apache
- 在VMWare Player上的T-Systems(托管虚拟化服务器)上运行的Life服务器
- 赢得2008 R2。Apache2.2.25+PHP5.4.26 NTS,VC9作为fastcgi模块
- 赢得2008 R2。Apache2.2.25+PHP5.5.1NTS,VC11作为fastcgi模块
- 赢得2008 R2。Apache 2.2.25+PHP5.5.1 NTS,VC11作为Apache模块
- Win2008R2、Apache2.2.25+PHP5.5.11TS、VC11作为Apache模块(这是我在更新2中提到的快速模块)
- 在本地计算机上,主机:OpenSuse,虚拟化:VMWare player,与@T-Systems相同。为避免其基础设施影响我们:
- 赢得2008 R2。Apache2.2.25+PHP5.4.26 NTS,VC9作为fastcgi模块
- 赢得2008 R2。IIS7+PHP 5.4.26 NTS,VC9作为fastcgi模块(带或不带wincache)
- 赢得2012年。IIS*+PHP 5.5.10 NTS,VC11作为fastcgi模块(带或不带wincache)
- 在没有虚拟化的本地计算机上
- 赢得2008 R2。Apache2.2.25+PHP5.4.26 NTS,VC9作为fastcgi模块
上述分析结果在不同的系统上是相同的(约10%的偏差)。Windows总是比Linux慢的一个重要因素
使用新安装的WordPress&Slimstats获得了大致相同的结果。在这里,重写代码不是一个选项
更新:与此同时,我们发现了另外两个Windows系统(都是Windows 2008 R2、VM和Phys),整个堆栈运行速度非常快。但配置相同
更新2:在Life服务器上以apache模块的形式运行PHP比fastcgi方法稍微快一点:低至2秒,减少50%
内存不足
几分钟后
PHP Fatal error: Out of memory (allocated 4456448) (tried to allocate 136 bytes)
PHP Fatal error: Out of memory (allocated 8650752) (tried to allocate 45 bytes)
PHP Fatal error: Out of memory (allocated 6815744) (tried to allocate 24 bytes)
Server version: Apache/2.4.7 (Win32)
Apache Lounge VC10 Server built: Nov 26 2013 15:46:56
Server's Module Magic Number: 20120211:27
Server loaded: APR 1.5.0, APR-UTIL 1.5.3
Compiled using: APR 1.5.0, APR-UTIL 1.5.3
Architecture: 32-bit
Server MPM: WinNT
threaded: yes (fixed thread count)
forked: no
Server compiled with....
-D APR_HAS_SENDFILE
-D APR_HAS_MMAP
-D APR_HAVE_IPV6 (IPv4-mapped addresses disabled)
-D APR_HAS_OTHER_CHILD
-D AP_HAVE_RELIABLE_PIPED_LOGS
-D DYNAMIC_MODULE_LIMIT=256
-D HTTPD_ROOT="/apache"
-D SUEXEC_BIN="/apache/bin/suexec"
-D DEFAULT_PIDLOG="logs/httpd.pid"
-D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
-D DEFAULT_ERRORLOG="logs/error.log"
-D AP_TYPES_CONFIG_FILE="conf/mime.types"
-D SERVER_CONFIG_FILE="conf/httpd.conf"
<IfModule mpm_winnt_module>
ThreadsPerChild 150
ThreadStackSize 8388608
MaxConnectionsPerChild 0
</IfModule>
realpath_cache_size = 12M
pcre.recursion_limit = 100000