什么会导致fastcgi_finish_request需要几秒钟才能执行?

时间:2013-05-15 21:14:27

标签: php performance fastcgi

我遇到了一个与大型PHP应用程序的特定部分相当奇怪的问题。有问题的应用程序部分从MySQL加载数据(主要是整数数据)并构建一个JSON字符串,输出到浏览器。这些请求在Chrome的开发人员工具以及curl中占用了sevar秒(每个8到10秒)。然而,PHP关闭处理程序我已经报告请求在不到1秒的时间内执行。

为了调试,我添加了对fastcgi_finish_request()的调用,突然我的关机处理程序报告与Chrome / curl同时发生。

通过一些调试,我将其缩小到一个特定的功能。我创建了以下简单的测试用例:

<?php

$start_time = DFStdLib::exec_time();
$product = new ApparelQuoteProduct(19);
$pmatrix = $product->productMatrix();

// This function call is the problem:
$ranges = $pmatrix->ranges();

$end_time = DFStdLib::exec_time();
$duration =  $end_time - $start_time;

echo "Output generation duration was: $duration sec";
fastcgi_finish_request();
$fastcgi_finish_request_duration =  DFStdLib::exec_time() - $end_time;
DFSkel::log(DFSkel::LOG_INFO,"Output generation duration was: $duration sec; fastcgi_finish_request Duration was: $fastcgi_finish_request_duration sec");

如果我调用$pmatrix->ranges()(这是一个对mysql_query执行大量调用以获取数据并从该数据构建内存中的PHP对象结构的函数),那么我得到输出:

  

输出生成持续时间为:0.2563910484314秒; fastcgi_finish_request持续时间为:7.3854329586029秒

在我的日志文件中。请注意,$pmatrix->ranges()的调用并不需要很长时间,但不知何故,它会导致PHP FastCGI处理程序需要7秒才能完成请求。 (即使我不调用fastcgi_finish_request也是如此 - 浏览器需要7-8秒才能显示数据)

如果我注释掉$pmatrix->ranges()的电话,我会:

  

输出生成持续时间为:0.0016419887542725秒; fastcgi_finish_request持续时间为:0.00035214424133301秒

我可以发布$pmatrix->ranges()函数的整个源代码,但它很长。我想在哪里开始寻找一些建议。

什么是PHP FastCGI请求进程甚至会导致这种行为?它是否调用析构函数/垃圾收集?它是否关闭开放资源?我该如何进一步解决这个问题?


编辑:这是一个更大的源样本:

<?php

class ApparelQuote_ProductPricingMatrix_TestCase
{
    protected $myProductId;
    protected $myQuantityRanges;

    private $myProduct;
    protected $myColors;
    protected $mySizes;

    protected $myQuantityPricing;

    public function __construct($product)
    {
        $this->myProductId = intval($product);
    }

    /**
     * Return an array of all ranges for this matrix.
     *
     * @return array
     */
    public function ranges()
    {
        $this->myLoadPricing();
        return $this->myQuantityRanges;
    }

    protected function myLoadPricing($force=false)
    {
        if($force || !$this->myQuantityPricing)
        {
            $this->myColors = array();
            $this->mySizes = array();

            $priceRec_finder = new ApparelQuote_ProductPricingRecord();
            $priceRec_finder->_link = Module_ApparelQuote::dbLink();
            $found_recs = $priceRec_finder->find(_ALL,"`product_id`={$this->myProductId}","`qtyrange_id`,`color_id`");

            $qtyFinder = new ApparelQuote_ProductPricingQtyRange();
            $qtyFinder->_link = Module_ApparelQuote::dbLink();
            $this->myQuantityRanges = $qtyFinder->find(_ALL,"`product_id`=$this->myProductId");

            $this->myQuantityPricing = array();

            foreach ($found_recs as &$r)
            {
                if(false) $r = new ApparelQuote_ProductPricingRecord();

                if(!isset($this->myColors[$r->color_id]))
                    $this->myColors[$r->color_id] = true;

                if(!isset($this->mySizes[$r->size_id]))
                    $this->mySizes[$r->size_id] = true;

                if(!is_array($this->myQuantityPricing[$r->qtyrange_id]))
                    $this->myQuantityPricing[$r->qtyrange_id] = array();

                if(!is_array($this->myQuantityPricing[$r->qtyrange_id][$r->color_id]))
                    $this->myQuantityPricing[$r->qtyrange_id][$r->color_id] = array();

                $this->myQuantityPricing[$r->qtyrange_id][$r->color_id][$r->size_id] = &$r;
            }

            $this->myColors = array_keys($this->myColors);
            $this->mySizes = array_keys($this->mySizes);
        }
    }
}

$start_time = DFStdLib::exec_time();
$pmatrix = new ApparelQuote_ProductPricingMatrix_TestCase(19);
$ranges = $pmatrix->ranges();
$end_time = DFStdLib::exec_time();
$duration =  $end_time - $start_time;

echo "Output generation duration was: $duration sec";
fastcgi_finish_request();
$fastcgi_finish_request_duration =  DFStdLib::exec_time() - $end_time;
DFSkel::log(DFSkel::LOG_INFO,"Output generation duration was: $duration sec; fastcgi_finish_request Duration was: $fastcgi_finish_request_duration sec");

继续调试后,我已经缩小到以上几行:

                if(!is_array($this->myQuantityPricing[$r->qtyrange_id][$r->color_id]))
                    $this->myQuantityPricing[$r->qtyrange_id][$r->color_id] = array();

这些语句构建了从MySQL加载的所有数据的内存数组结构。如果我评论这些,那么fastcgi_finish_request大约需要0.0001秒才能运行。如果我不对它们进行评论,则fastcgi_finish_request需要7秒以上才能运行。

这实际上是is_array的函数调用,这是

的问题

更改为:

                if(!isset($this->myQuantityPricing[$r->qtyrange_id][$r->color_id]))

解决了这个问题。这是为什么?

0 个答案:

没有答案