编辑:事实证明,$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
的调用都将针对不同的文章,所以不能走捷径。
你可以做两件事:
- 仅用
$article->id
替换$article->getID()
- 使你的外循环跨文章,使你的内循环跨令牌。通过这种方式,您可以在一篇文章中保留一整批令牌,这将有助于缓存