在php数组中存储大量文件指针

在php数组中存储大量文件指针,php,arrays,file,Php,Arrays,File,所以我有一个需要优化的特定脚本。事实上,我要读一个160gB的文件,每行我都要存储md5散列的前两个字母和普通字 我确实在测试代码中加入了一些计时器来检查瓶颈,其中一个大问题当然是文件编写 我有16^4个文件要处理。现在,我把所有东西都写在缓冲区中,只有当缓冲区达到一定大小时(根据我的ram),我才会将其打印到文件中 问题是,我仍然必须为每个文件每次打开、写入和关闭。这需要很长时间。我运行了一些基准测试,在for循环之前使用fopen,在循环之后使用fclose确实将速度提高了20倍(显然) 所

所以我有一个需要优化的特定脚本。事实上,我要读一个160gB的文件,每行我都要存储md5散列的前两个字母和普通字

我确实在测试代码中加入了一些计时器来检查瓶颈,其中一个大问题当然是文件编写

我有16^4个文件要处理。现在,我把所有东西都写在缓冲区中,只有当缓冲区达到一定大小时(根据我的ram),我才会将其打印到文件中

问题是,我仍然必须为每个文件每次打开、写入和关闭。这需要很长时间。我运行了一些基准测试,在for循环之前使用fopen,在循环之后使用fclose确实将速度提高了20倍(显然)

所以我在想,为什么我不制作一个数组,就像我必须存储65536缓冲区的数组一样,来存储文件指针

我试过了,但有个错误。这是我的密码:

for($i = 0;$i < 16;$i++)
{
for($j = 0;$j < 16;$j++)
{
for($k = 0;$k < 16;$k++)
{
for($l = 0;$l < 16;$l++)
{
     $ijkl = $hexa[$i].$hexa[$j].$hexa[$k].$hexa[$l];
     $fichiers[] = $ijkl;
     $fichiers[$ijkl] = [];
     $fichiers[$ijkl][0] = fopen(realpath("my/path/to/" . $hexa[$i] . "/" . $hexa[$j] . 
     $hexa[$k] . $hexa[$l]),"a");
}
}
}
}
($i=0;$i<16;$i++)的

{
对于($j=0;$j<16;$j++)
{
对于($k=0;$k<16;$k++)
{
对于($l=0;$l<16;$l++)
{
$ijkl=$hexa[$i]。$hexa[$j]。$hexa[$k]。$hexa[$l];
$fichiers[]=$ijkl;
$fichiers[$ijkl]=[];
$fichiers[$ijkl][0]=fopen(realpath(“my/path/to/”)$hexa[$i]。“/”$hexa[$j]。
$hexa[$k]。$hexa[$l]),“a”);
}
}
}
}
所以,当我运行这个时,我有两个不同的错误。第一个是“无法打开流:文件存在”,这似乎很难理解,因为它确实创建了每个文件,即使它打印了这个错误

第二个是“打开流失败;参数无效”。根据我在stackoverflow上看到的几个帖子,这就是路径。这就是我在这里尝试realpath的原因。我还尝试了“my\path\to\”和“my\path\to”,但没有成功。这很奇怪,因为当所有的FOPEN都在for循环期间生成时,它通常会工作

是否有任何东西阻止我们创建文件指针数组

谢谢你的回答:)

编辑:实际上这是我的全部代码:

<?php
set_time_limit(3600000);
ini_set('memory_limit', '4096M');
$time_pre = microtime(true);
$chunkSize = (1<<29);
$bufferSize = (1<<15);
$position = 0;
$filesize = filesize("my\\path\\to\\file");
$dico = fopen("my\\path\\to\\file","r+");
$hexa = array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
for($i = 0;$i < 16;$i++)
{
    for($j = 0;$j < 16;$j++)
    {
        for($k = 0;$k < 16;$k++)
        {
            for($l = 0;$l < 16;$l++)
            {
                $ijkl = "$hexa[$i]$hexa[$j]$hexa[$k]$hexa[$l]";
                $$ijkl = "";
            }
        }
    }
}
while(!feof($dico))
{
    fseek($dico, $position);
    $chunk = fread($dico, $chunkSize);
    $last_lf_pos = strrpos($chunk, "\n");
    $buffer = mb_substr($chunk,0,$last_lf_pos);
    $tab = explode("\n",$buffer);
    $limiteBuffer = count($tab);

    for($i = 0;$i < $limiteBuffer;$i++)
    {
        $md5 =  md5($tab[$i]);
        $add4 = "$md5[0]$md5[1]$md5[2]$md5[3]";
        $$add4 .= "$md5[4]$md5[5]$tab[$i]\n";
        if(isset($$add4{$bufferSize}))
        {
            $baseFichier = "my\\path\\to\\$md5[0]\\$md5[1]$md5[2]$md5[3]";
            $fichier = fopen($baseFichier,"a");
            fwrite($fichier, $$add4);
            fclose($fichier);
            $$add4 = "";
        }
    }
    for($i = 0;$i < 16;$i++)
    {
        for($j = 0;$j < 16;$j++)
        {
            for($k = 0;$k < 16;$k++)
            {
                for($l = 0;$l < 16;$l++)
                {
                    $ijkl = "$hexa[$i]$hexa[$j]$hexa[$k]$hexa[$l]";
                    if($$ijkl != "")
                    {
                        $baseFichier = "my\\path\\to\\$hexa[$i]\\$hexa[$j]$hexa[$k]$hexa[$l]";
                        $fichier = fopen($baseFichier,"a");
                        fwrite($fichier, $$ijkl);
                        fclose($fichier);
                        $$ijkl = "";
                    }
                }
            }
        }
    }
    $position += $last_lf_pos;
    if(($position+$chunkSize) > $filesize) $chunkSize = $filesize-$position;
        $buffer = NULL;

}
fclose($dico);
$time_post = microtime(true);
$exec_time = $time_post - $time_pre;
echo "Total : " .$exec_time;
?>


如果你对速度优化有任何想法。

我会认真考虑使用数据库(SQLite),而不是一堆文件。首先,你会为每个文件或者仅仅在一个点之后得到这些错误。第二,你在任何时候都可以打开的文件数量是有限制的,你很可能接近或超过这个限制,这看起来总的来说是个坏主意。谢谢你的回答。我确实尝试过数据库,但我的系统实际上运行得更好。我只是创建这些文件,然后我只需要寻找特定的行。数据库会很快,但也会占用更多的磁盘空间(我们所说的总数超过1000亿行)。创建4095个文件后,该错误确实会出现。我想这是最大值。谢谢你的回答。别担心,这不是生产代码,这是本地代码,这就是为什么我要尝试疯狂的事情。我过去也做过类似的事情,第一个提示是,你要用4096个文件创建16个目录,最好用256个文件创建256个目录(速度更快)。询问该问题时,不可能在单个文件中使用指针计算绝对位置?。你在这些文件中存储了什么?如果我得到它,输入是一个160gb的单个文件,输出是每行一个“哈希”和这些行的纯文本,存储在65536个文件中的一个(基于先前计算的哈希)?