php apc require once,为什么require_once如此糟糕?

我很好奇并检查了Adam Backstrom与Tech Your Universe的链接。本文介绍了应该使用require而不是require_once的原因之一。但是,他们的说法并不符合我的分析。我有兴趣看到我可能错误地分析了解决方案。我使用php 5.2.0进行比较。

我开始创建100个头文件,使用require_once包含另一个头文件。每个文件看起来像:<?php // /home/fbarnes/phpperf/hdr0.phprequire_once "../phpperf/common_hdr.php";?>

我使用快速bash hack创建了这些:for i in /home/fbarnes/phpperf/hdr{00..99}.php; do

echo "<?php

// $i" > $i

cat helper.php >> $i;done

通过这种方式,我可以轻松地在使用require_once和包含头文件时的require之间进行切换。然后我创建了一个app.php来加载一百个文件。这看起来像:<?php // Load all of the php hdrs that were created previouslyfor($i=0; $i < 100; $i++){

require_once "/home/fbarnes/phpperf/hdr$i.php";}// Read the /proc file system to get some simple stats$pid = getmypid();$fp = fopen("/proc/$pid/stat", "r");$line = fread($fp, 2048);$array = split(" ", $line);// write out the statistics; on RedHat 4.5 w/ kernel 2.6.9// 14 is user jiffies; 15 is system jiffies$cntr = 0;foreach($array as $elem){

$cntr++;

echo "stat[$cntr]: $elem\n";}fclose($fp);?>

我将require_once标头与使用头文件的require标头进行了对比,如下所示:<?php // /home/fbarnes/phpperf/h/hdr0.phpif(!defined('CommonHdr')){

require "../phpperf/common_hdr.php";

define('CommonHdr', 1);}?>

使用require与require_once运行时,我发现没有太大区别。事实上,我的初步测试似乎暗示require_once略快,但我不一定相信。我用10000输入文件重复了实验。在这里,我确实看到了一致的差异。我多次运行测试,结果很接近,但使用require_once平均使用30.8个用户jiffies和72.6个系统jiffies; 使用require平均使用39.4用户jiffies和72.0系统jiffies。因此,使用require_once看起来负载略低。但是,挂钟略有增加。10,000个require_once调用平均使用10.15秒完成,10,000个需要调用平均使用9.84秒。

下一步是研究这些差异。我使用strace来分析正在进行的系统调用。

在从require_once打开文件之前,会进行以下系统调用:time(NULL)                              = 1223772434lstat64("/home", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0lstat64("/home/fbarnes", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0lstat64("/home/fbarnes/phpperf", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0lstat64("/home/fbarnes/phpperf/h", {st_mode=S_IFDIR|0755, st_size=270336, ...}) = 0lstat64("/home/fbarnes/phpperf/h/hdr0.php", {st_mode=S_IFREG|0644, st_size=88, ...}) = 0time(NULL)                              = 1223772434open("/home/fbarnes/phpperf/h/hdr0.php", O_RDONLY) = 3

这与要求形成对比:time(NULL)                              = 1223772905lstat64("/home", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0lstat64("/home/fbarnes", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0lstat64("/home/fbarnes/phpperf", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0lstat64("/home/fbarnes/phpperf/h", {st_mode=S_IFDIR|0755, st_size=270336, ...}) = 0lstat64("/home/fbarnes/phpperf/h/hdr0.php", {st_mode=S_IFREG|0644, st_size=146, ...}) = 0time(NULL)                              = 1223772905open("/home/fbarnes/phpperf/h/hdr0.php", O_RDONLY) = 3

Tech Your Universe暗示require_once应该进行更多的lstat64调用。但是,它们都进行了相同数量的lstat64调用。可能的不同之处在于我没有运行APC来优化上面的代码。但是,我接下来要做的是比较整个运行的strace输出:[fbarnes@myhost phpperf]$ wc -l strace_1000r.out strace_1000ro.out

190709 strace_1000r.out

210707 strace_1000ro.out

401416 total

使用require_once时,每个头文件大约有两个系统调用。一个区别是require_once有一个额外的time()函数调用:[fbarnes@myhost phpperf]$ grep -c time strace_1000r.out strace_1000ro.out strace_1000r.out:20009strace_1000ro.out:30008

另一个系统调用是getcwd():[fbarnes@myhost phpperf]$ grep -c getcwd strace_1000r.out strace_1000ro.out strace_1000r.out:5strace_1000ro.out:10004

这是因为我决定在hdrXXX文件中引用的相对路径。如果我将它作为绝对引用,那么唯一的区别是在代码中进行的附加时间(NULL)调用:[fbarnes@myhost phpperf]$ wc -l strace_1000r.out strace_1000ro.out

190705 strace_1000r.out

200705 strace_1000ro.out

391410 total[fbarnes@myhost phpperf]$ grep -c time strace_1000r.out strace_1000ro.outstrace_1000r.out:20008strace_1000ro.out:30008

这似乎意味着您可以通过使用绝对路径而不是相对路径来减少系统调用的数量。除此之外的唯一区别是时间(NULL)调用,它们似乎用于检测代码以比较更快的代码。

另一个注意事项是APC优化包有一个名为“apc.include_once_override”的选项,它声称它减少了require_once和include_once调用所进行的系统调用次数(参见PHP文档)。

对不起,很长的帖子。我很好奇。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值