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