为什么将isset应用于多维数组会将执行时间增加4000%


Why applying isset to a multidimensional array increased execution time by 4000%?

编辑:事实证明,$article->getID();是导致执行时间过大的部分。以下是它的样子:

public function getId()
{
    return $this->id;
}

但我仍然不知道为什么会发生这种事。


我正在使用此代码尝试为1000个文档和4000个唯一标记的小语料库中的每个标记计算document frequency

为此,我编写了以下函数:

public function computeIDF(){
    // splitting documents into tokens
    $this->tokens = $this->tokenize();
    // $this->tokens = array($article->id => array($token => $freq))
    // 1. For each token …
    foreach($this->tokens as $token){
        // 2. … look in every document …
        foreach($this->articles as $article){
            // 3. … and if it exists there …
            if(isset($this->tokens[$article->getID()][$token]){
                // 4. … add 1
                $tokFreq[$token] += 1;
            }
        }
    }
}

但是第三步。造成了很多麻烦:
-如果我注释掉步骤4.,则没有任何变化
-如果我注释掉步骤3.,执行时间从414.2s变为"刚好"14s,这几乎快了4000%!!1.(所以,毫无疑问,这不是一个"微观优化"问题

注意此处不涉及数据库。所有的东西都在更早的时候被提取出来,超出了整个class的范围:

// This is where the data is being fetched
$articles = ArticleDAO::loadLast(1000);
// It's then injected into the $corpus
$corpus = new Corpus($articles);

我是不是做错了什么?如果是的话,我该如何让事情变得更快?

$article->getID()的每个调用都有开销。它必须保存堆栈,调用函数,复制结果,然后继续。因为您正在为每篇文章迭代每个令牌(而不是反过来(,所以每次对getID的调用都将针对不同的文章,所以不能走捷径。

你可以做两件事:

  1. 仅用$article->id替换$article->getID()
  2. 使你的外循环跨文章,使你的内循环跨令牌。通过这种方式,您可以在一篇文章中保留一整批令牌,这将有助于缓存