【问题标题】:PHP Runtime Performance DebuggingPHP 运行时性能调试
【发布时间】:2014-06-16 21:09:51
【问题描述】:

我有一个简单的 PHP 脚本,可以对 Mongo 数据库进行一些更新:

$properties = db()->properties->find([], ['_id' => true]);
foreach($properties as $property) {
  db()->properties->update(
    ['_id' => $property['_id']],
    ['$set' => ['random' => [lcg_value(), lcg_value()]]],
    ['w' => 0]
  );
}

我基本上按照here 的建议为“属性”集合中的每个记录分配一个随机点,以查询随机记录。对于我正在操作的数据集(大约 200,000 个文档),此脚本在我的本地系统上运行大约一分半钟。

我考虑使用 JavaScript 并在服务器端运行更新,但从驱动程序运行服务器端代码需要过于宽松的特殊权限。我不喜欢我必须拉下所有数据并为每条记录发送更新但我想不出在 Mongo 中作为批处理操作的方法。

无论网络流量过多,它都相当快,因为​​我只是拉下 ID,而我对数据库的写回没有启用写一致性。

在生产机器上运行此脚本时,脚本突然需要更长的时间。大约 30 分钟后,我终止了这项工作。出于各种其他原因,生产站点使用自定义编译的 PHP 安装。我认为自定义编译是原因,但我不确定如何追踪减速的确切原因。

到目前为止我的想法:

  • 可能在我的机器上启用的生产机器上没有启用某些优化模块?我假设像 opcache 这样的东西不会影响这一点,因为我们只执行一次 CLI 脚本,而不是向同一个脚本发出一堆请求。
  • 也许某些编译时选项可以使 gcc 生成更优化的二进制文件?
  • 或者 Mongo 模块的通信速度较慢,因为它缺少一些更快的网络库,必须退回到较慢的库?

自定义编译的 PHP 使用以下选项和模块进行编译:

./configure --enable-static --enable-cli --disable-all --with-curl \
  --enable-mongo --enable-json --enable-hash --enable-libxml \
  --enable-simplexml --enable-filter --enable-dom --enable-ftp \
  --enable-pcntl --enable-posix --enable-xmlwriter

如果我在本地系统模块和这个自定义编译版本之间进行比较,我会得到以下模块,这些模块在我的本地系统上,但不在生产机器上:

bz2
calendar
ctype
exif
fileinfo
gettext
iconv
mhash
mysql
mysqli
mysqlnd
openssl
PDO
pdo_mysql
pdo_sqlite
Phar
readline
session
shmop
sockets
sqlite3
sysvmsg
sysvsem
sysvshm
tokenizer
wddx
xdebug
xml
xmlreader
xsl
zip
zlib

这些看起来都不会影响性能。

比较版本你可以看到我正在运行类似的版本。自定义版本:

PHP 5.5.13 (cli) (built: Jun 11 2014 17:00:10) 
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies

我的本​​地机器:

PHP 5.5.12 (cli) (built: May  3 2014 07:09:53) 
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
  with Xdebug v2.2.5, Copyright (c) 2002-2014, by Derick Rethans

我假设缓慢是由于 IO 而不是 CPU,因为脚本主要是关于与 Mongo 数据库通信。它确实计算了一个随机数,但这并没有考虑在内,因为我自定义编译的 PHP 实际上更快地生成了随机数。在我的本地 php 上使用 lcg_value 生成一百万个随机数:

real 0m0.420s
user 0m0.411s
sys  0m0.008s

但是使用我自定义编译的 PHP:

real 0m0.081s
user 0m0.076s
sys  0m0.005s

问题不是由于生产环境的网络或 CPU 能力。我在本地机器上运行了自定义编译的 PHP 二进制文件,它的速度也明显变慢了。所以我很确定这与它的编译方式、使用的模块或配置有关。

有人知道下一步要去哪里吗?

【问题讨论】:

  • 告诉我们有关磁盘驱动器以及 prod 系统上正在运行的其他内容。是否有其他东西同时运行?它是否被用于其他任何事情? prod 和您的测试/开发机器之间还有什么不同?
  • 您是否对代码进行了概要分析,以便更好地了解您将时间花在哪里?我认为这将是下一个合乎逻辑的步骤。
  • @AlisterBulman - 与生产系统无关。注意我的最后一段。如果我在本地系统(而不是系统范围的 PHP)上使用相同的 PHP 二进制文件,它也会运行缓慢。因此,自定义 PHP 在我的系统和服务器上运行缓慢。我的本地系统范围的二进制文件运行速度并不慢。

标签: php performance mongodb gcc compiler-optimization


【解决方案1】:

@mike-brant 为我指明了正确的方向。

我将 Xdebug 模块添加到自定义编译的 PHP 二进制文件中。使用自定义二进制文件与我的本地系统二进制文件运行脚本。自定义二进制文件大部分时间都花在了更新功能上。由于写入关注设置为 0,因此更新应该非常快。在我的本地系统中,更新仅占运行时间的 10%。但是对于自定义 PHP,它的 97%。

这让我觉得这个问题是 Mongo 驱动程序之间的一些差异。自定义二进制文件使用的是 1.5.3,我的本地系统是 1.4.4。

我将对此进行进一步调查(可能针对不同的 StackOverflow 问题)。但@mike-brant 回答了我的直接问题,即如何精确定位查看位置。

【讨论】:

  • 对任何感兴趣的人的进一步更新。此 QA 缩小范围以进行更新。一些研究表明,从 1.5 开始,即使我将写入关注度设置为 0,Mongo 也不再支持 fire and forget 这意味着它正在等待回复。使用批量更新 API 允许我重新编写脚本以使其更快。更新调试见this QA
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多