【问题标题】:speed string search in PHPPHP中的快速字符串搜索
【发布时间】:2011-03-01 22:06:53
【问题描述】:

我有一个 1.2GB 的文件,其中包含一个单行字符串。 我需要的是搜索整个文件以找到另一个字符串的位置(目前我有一个要搜索的字符串列表)。 我现在做的方式是打开大文件并将指针移过 4Kb 块,然后将指针 X 位置移回文件中并获得 4Kb 更多。

我的问题是要搜索的字符串越大,他得到它的时间就越长。

您能给我一些想法来优化脚本以获得更好的搜索时间吗?

这是我的实现:

function busca($inici){
        $limit = 4096;

        $big_one    = fopen('big_one.txt','r');
        $options    = fopen('options.txt','r');

        while(!feof($options)){
            $search = trim(fgets($options));
            $retro  = strlen($search);//maybe setting this position absolute? (like 12 or 15)

            $punter = 0;
            while(!feof($big_one)){
                $ara = fgets($big_one,$limit);

                $pos = strpos($ara,$search);
                $ok_pos = $pos + $punter;

                if($pos !== false){
                    echo "$pos - $punter - $search : $ok_pos <br>";
                    break;
                }

                $punter += $limit - $retro;
                fseek($big_one,$punter);
            }
            fseek($big_one,0);
        }
    }

提前致谢!

【问题讨论】:

  • 对 1.2GB 文件使用普通的 strpos() 函数会发生什么?
  • 我在 PHP 中找到了一个针对不同匹配方法的基准,但 strpos() 是最快的。 hashbangcode.com/blog/fastest-way-match-string-php-200.html
  • options.txt 有多大,它长什么样子?
  • powtac,我不是一次打开 1.2GB 的,我是分段打开的,它只浪费 32MB 的 RAM(大约)。 0scar,options.txt 有 25000000 万行(选项为 50M)。
  • powtac,我已经阅读了一些关于 strpos 的类似基准,因此我正在寻找脚本所有部分的优化。

标签: php string search performance


【解决方案1】:
$big_one    = fopen('big_one.txt','r');
$options    = fopen('options.txt','r');  

while(!feof($options))
{
  $option = trim(fgets($options));
  $position = substr($big_one,$option);

  if($position)
    return $position; //exit loop
}

文件的大小虽然很大。您可能要考虑将数据存储在数据库中。或者如果您绝对不能,请使用此处发布的 grep 解决方案。

【讨论】:

  • 例如可能将其插入 4Kb 的块中?那 foreach 是用来分割字符串的吗?还是什么?
【解决方案2】:

为什么不使用exec + grep -b

exec('grep "new" ext-all-debug.js -b', $result);
// here we have looked for "new" substring entries in the extjs debug src file
var_dump($result);

样本结果:

array(1142) {
    [0]=>  string(97) "3398: * insert new elements. Revisiting the example above, we could utilize templating this time:"
    [1]=>  string(54) "3910:var tpl = new Ext.DomHelper.createTemplate(html);"
    ...
}

每个项目由从文件开头和行本身开始的字符串偏移量(以字节为单位)组成,用冒号分隔。
因此,在此之后,您必须查看特定行内部并将位置附加到行偏移量。即:

[0]=>  string(97) "3398: * insert new elements. Revisiting the example above, we could utilize templating this time:"

这意味着在第 3408 个字节发现“新”出现(3398 是行位置,10 是该行内“新”的位置)

【讨论】:

  • +1。当您处理这么大的文件时,最好将此类工作留给专为该工作构建的工具。
  • 我同意这个想法,但我需要正确的方式来启动 grep。用 grep 在文件中搜索字符串的正确句子是什么?它可以返回我的匹配位置吗?谢谢
  • 非常感谢 zerkms!,我会做基准来告诉你它是如何提高性能的。
  • @zerkms 我现在遇到的问题是 grep 和输出,他给了我整行,而我在这个 Hughe 文件中的所有内容都在一行中,然后他给了我数字位置具有我无法管理的非常laaaaaaarge的输出。知道如何只输出第一个位置然后退出 grep 吗? (类似于带输出的 -q 或不带整行的 -m 1 )。提前致谢
猜你喜欢
  • 2013-01-20
  • 2013-01-06
  • 2012-01-22
  • 2010-12-18
  • 2018-02-03
  • 2014-11-24
  • 2011-03-22
  • 2014-09-19
  • 2020-04-09
相关资源
最近更新 更多