file_get_contents和file_put_contents是可靠的还是会导致数据丢失?基准结果

问题描述 投票:0回答:1

我想知道如果多个脚本共享同一文件会发生什么。我将测试上传到远程服务中,我知道他们使用HDD来存储数据。共有7个测试,但6个测试家族是兼容的。

我有7个不同大小的文件,已上传到服务器和测试。这是从文件读取和写入数据的循环。

循环中有50微秒的延迟。循环重复50倍。

我测量完成每个圆圈所需的时间。

测试差异(T):

使用file_get_contents / file_put_contents

T2-源<>目标-从原始文件读取数据,将数据写入其他(新)文件中

T3-源=目标-1.将数据从原始文件复制到目标; 2.读取源数据->写入数据; 3.重复第3点:即,我读取了已写入的数据。该测试使用相同的文件来写入数据。

T4-源=目标-我重复了与T3中相同的测试,只是缩短了时间。

使用fopen,flock,fread,flock,fclose,fopen,flock,fopen,fwrite,fflush,fclock,fclose...。这是复杂的代码,但是这里我已经测试了fflush。我还使用clearstatcache,stat和touch和clearstatcache,filesize。检查有效性。测试T5-T7不如T2-T4可靠,因为有时写入操作失败。我测试了文件大小,当它不正确时,我从原始文件中复制(还原)了该文件。

T5 :(模糊)源=目标

T6 :(模糊)源<>目标

T7 :(模糊)源<>目标+我从循环中删除了50微秒的延迟(似乎有延迟,有效性/可靠性更差)。

我从4个不同的浏览器发出了4个请求-因此每个测试都有4组数据(总共7 * 50 * 4个值)。

现在我已经收集了所有数据,创建了表格和图表。这是很多图中的一个,显示了平均值的最小和最大值。

T4黄色和T3绿色提供的时间非常短,因此很可疑。例如,T4的平均时间为:0,001

0.001 0.002 0.003 0.002 0.004 0.003 0.004 0.001 0.004 0.001 0.004 0.001 0.004

和T3次:

0.002 0.003 0.001 0.001 0.003 0.003 0.006 0.007 0.002 0.003 0.004 0.004 0.019 0.019

T2的值似乎是正常的,但这可以通过以下事实来解释,即从不同的文件读取的文件与写入的文件不同。

T5-T7只是按预期显示正常时间-文件越大,处理所需的时间就越大。与同时运行的HDD和4个脚本所预期的相当慢。

所以我的问题是:

T3-T4的结果是否表示file_read_contents和file_put_contents对于这种类型的作业不可靠?在我看来,它们只是不从文件中读取数据,而是从缓冲区中复制数据,这意味着将保存旧数据,而不是通过并发脚本更改当前数据。欢迎提供更多信息。我花了很多时间寻找答案,但是没有找到明确的答案。我进行此测试是因为我需要证明。你们想使用我的脚本,但是我不确定是否可以将6个脚本粘贴到这里?现在,我将仅添加最有用的fflush测试编号7。

<?PHP 
clearstatcache();
$_DEBUG_ = false;

echo "Lock and flush tester.".time()."<br>";
die;

while ( time()<1570787996 )
 {
 usleep(500);
 }


function test($n, $p, $_DEBUG_){
  $sname = "$n";    // source
  $tname = "$n.txt";// target
  echo "<h4>$n at ".time()."</h4>";
  for ($i = 0; $i<50; $i++ ){
    $start = microtime(true);
    clearstatcache(); // needed for filesize and touch    
    $st = stat("$sname");
    $original_size = $st['size'];
    if ( $_DEBUG_ )
      echo "; 1) prevAccess by ".$st['mtime']." fsize ".$st['size']."; ";
    $fsize = filesize($sname);
    if ( $original_size <> $fsize )
      die("; fsize total FAILTURE; ");
    if ($fsize === 0)
     echo "! <b>The fsize is 0</b>: stat(): ".$st['size']." ;";    
    else
      {
      // READ OPERATION AND LOCK FOR SHARE
       $locked = false;     
       for ($c = 0; !$locked; $c++):      
         if ( $c > 400)
           break;
         $fp = fopen($sname, "r");
         $locked = flock($fp, LOCK_SH);
         if ($locked)
           break;
         else
           {
           echo "failed to get LOCK_SH;<br>";
           usleep(5000);
           }
       endfor;
       $s = fread($fp, $fsize );
       $success = flock($fp, LOCK_UN);
       if ( $success === false  )
         die("; r flock release failed; ");
       $success = fclose($fp);
       if ( $success === false  )
         die("; fclose failed; ");
       // 10 - data loaded , $p - browser
       if ( $success )
         { 
         $result = touch("$sname",strlen($s),$p);
         if ( $_DEBUG_ )
            echo "; TOUCH: $result;";
         }
       else
         die("fclose FAIL.");
       if ( strlen($s)<60 ) 
          echo "*$s LENGTH:".strlen($s)."<br>";
      }
    clearstatcache();
    $st = stat("$tname");                               
    if ( $_DEBUG_ )
      echo "; 2) prevAccess by ".$st['mtime']." fsize is ".$fsize."; ";

    // WRITE OPERATION WITH LOC_EX
    $fp = fopen($tname, "w");
    $locked = false; 
    $locked = flock($fp, LOCK_EX);
    if ( $locked ) {  // acquire an exclusive lock
        $success = fwrite($fp, $s);
        if ( $success === false)
          echo "; w FAILED;";
        else
          if ( $_DEBUG_ )
                echo " $success B written; ";
        $success = fflush($fp);// flush output before releasing the lock
        if ( $success === false ) 
          echo "; flush FAILED; ";
        $success = flock($fp, LOCK_UN);    // release the lock
        if ( $success === false ) 
          echo "; release FAILED; ";
        $success = fclose($fp);
        if ( $success === false ) 
          echo "; fclose FAILED; ";
        clearstatcache(); // needed for filesize and touch
        $fsize = filesize($tname);
        if ($original_size>$fsize)
            {
            echo "; <b>WRITE FAILED, restoring</b>;";
            $original_fname = "$n";
            $result = copy($original_fname, $tname);
            if ($result == false )
              die(" <b>TOTAL FAILTURE: copy failed.</b>");
            else
              echo " <b>RESTORED</b>;";
            }
        else
        {
          if ($fsize === 0)
           echo "! THE FILE WAS NOT WRITTEN: data length: ".strlen($s)." fsize: $fsize RESOURCE: $fp<br>";    
          if ( $success ) 
              touch("$tname",$fsize,$p);
        }
    } else {
        echo "Couldn't get the lock!";
    }
     $time_elapsed_secs = microtime(true) - $start;
     if ( $time_elapsed_secs === 0 )
       echo " FAILED ";
    echo "time: $time_elapsed_secs s<br>"; 
  }
}

switch ( $_SERVER['HTTP_USER_AGENT'] ):
  // FF 1:
  case "Mozilla/5.0 (Windows NT 5.1; rv:49.0) Gecko/20100101 Firefox/49.0": 
    $p = 1; break;
  // Chrome:
  case "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36":
    $p = 2; break;
  // OPERA:
  case "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36 OPR/36.0.2130.80":  
    $p = 3; break;
endswitch;

copy("523","523.txt");
copy("948","948.txt");
copy("1371","1371.txt");
copy("1913","1913.txt");
copy("2701","2701.txt");
copy("4495","4495.txt");
copy("6758","6758.txt");

test("523",$p,$_DEBUG_);
test("948",$p,$_DEBUG_);
test("1371",$p,$_DEBUG_);
test("1913",$p,$_DEBUG_);
test("2701",$p,$_DEBUG_);
test("4495",$p,$_DEBUG_);
test("6758",$p,$_DEBUG_);
die;
echo "php: " . phpversion();
?>
<?PHP echo "php: " . phpinfo();
?>

您可能要启用$ DEBUG选项来监视每个进程。注意:触摸可能无法始终正常工作。

注意:这不是测试要求,只是审查要求。

file_put_contents vs fflush

php file-get-contents file-put-contents fflush
1个回答
0
投票

太多阅读了,请简化您的问题,以获得更多获得回答的机会

© www.soinside.com 2019 - 2024. All rights reserved.