PHP运行时性能调试
我有一个简单的PHP脚本,可以对Mongo数据库进行一些更新:PHP运行时性能调试,php,performance,mongodb,gcc,compiler-optimization,Php,Performance,Mongodb,Gcc,Compiler Optimization,我有一个简单的PHP脚本,可以对Mongo数据库进行一些更新: $properties = db()->properties->find([], ['_id' => true]); foreach($properties as $property) { db()->properties->update( ['_id' => $property['_id']], ['$set' => ['random' => [lcg_value
$properties = db()->properties->find([], ['_id' => true]);
foreach($properties as $property) {
db()->properties->update(
['_id' => $property['_id']],
['$set' => ['random' => [lcg_value(), lcg_value()]]],
['w' => 0]
);
}
我基本上是为“properties”集合中的每个记录分配一个随机点,就像查询随机记录时建议的那样。对于我正在操作的数据集(大约200000个文档),该脚本在本地系统上运行大约一分钟半
我考虑过使用JavaScript并运行服务器端更新,但是从驱动程序运行服务器端代码需要特别的权限,这太过宽容了。我不喜欢这样一个事实,我必须拉下所有的数据,并发送每个记录的更新,但我无法想出一种方法来在Mongo中作为一个批处理操作
不管过多的网络流量,它都是相当快的,因为我只是拉下ID,而我对数据库的写回没有启用写一致性
在生产机器上运行此脚本时,脚本会突然花费更长的时间。大约30分钟后我就把工作干掉了。出于各种其他原因,生产站点使用自定义编译的PHP安装。我认为自定义编译是原因,但我不确定如何去追踪减速的确切原因
到目前为止,我的想法是:
- 可能在我的机器上启用的生产机器上未启用某些优化模块?我假设类似于opcache的东西不会影响这一点,因为我们只执行一次CLI脚本,而不是对同一脚本发出大量请求
- 也许有一些编译时选项可以让gcc生成一个更优化的二进制文件
- 或者Mongo模块的通信速度变慢了,因为它缺少一些更快的网络库,所以不得不退回到一个较慢的网络库
./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_值生成一百万个随机数:
real 0m0.420s
user 0m0.411s
sys 0m0.008s
但对于我的自定义编译PHP:
real 0m0.081s
user 0m0.076s
sys 0m0.005s
问题不是由于生产环境的网络或CPU能力造成的。我在本地机器上运行了自定义编译的PHP二进制文件,而且速度明显较慢。所以我很确定这与它的编译方式、使用的模块或配置有关
有人知道下一步该去哪里吗?@mike brant为我指出了正确的方向 我将Xdebug模块添加到定制编译的PHP二进制文件中。使用自定义二进制文件与我的本地系统二进制文件运行脚本。自定义二进制文件在更新函数中花费了大部分时间。由于写入问题设置为0,更新应该非常快。在我的本地系统中,更新只占运行时的10%。但使用定制PHP,它的使用率为97% 这让我觉得问题在于Mongo驱动程序之间的一些差异。自定义二进制文件使用1.5.3,我的本地系统是1.4.4
我将进一步调查这一点(可能是在另一个StackOverflow问题上)。但是@mike brant回答了我的直接问题,即如何进行pin定位。告诉我们有关磁盘驱动器以及prod系统上运行的其他内容。还有什么东西同时运行吗?它还用于其他用途吗?prod和您的测试/开发机器之间还有什么不同?您是否已经分析了您的代码,以便更好地了解您在哪里花费时间?“我认为这将是下一个合乎逻辑的步骤。”阿利斯特·鲍曼——这与生产系统无关。注意我的最后一段。如果我在本地系统上使用相同的PHP二进制文件(而不是系统范围的PHP),它也会运行缓慢。因此,自定义PHP在我的系统和服务器上都运行缓慢。我的本地系统范围二进制文件运行速度不慢。有兴趣的人可以进一步更新。这个QA缩小了范围以进行更新。一点研究表明,从1.5开始,Mongo不再支持fire and forget,这意味着它正在等待回复,即使我将write concert设置为0。使用批更新API使我能够重新编写脚本,使其速度更快。有关更新的调试,请参阅。