0

編集: この質問の最後に最適化の結果があります!

こんにちは、最初に特定のフォルダー内のファイルをスキャンし、次にすべてのファイルを 1 行ずつ読み取り、多数の "if...else if" の後に、新しい変更されたファイルを別のフォルダーに開いたときの名前で書き込む次のコードがあります。 .

問題は、ファイルを1行ずつ書き込むのが非常に遅いことです。デフォルトの 60 秒の制限は、25 程度のファイルに対してのみ十分です。ファイル サイズは 10k から 350k までさまざまです。

コードを最適化して実行を高速化する方法。行ごとに読み取り、すべての行を配列に入れてから、その配列全体を新しいテキストファイルに書き込む方が良いですか (行ごとの読み取り/書き込みに対して)。もしそうなら、それは実際にどのように行われますか。

よろしくお願いします ----- コードは次のとおりです -----

<?php

function scandir_recursive($path)    {
...
...
}



$fileselection = scandir_recursive('HH_new');
foreach ($fileselection as $extractedArray) {
$tableName = basename($extractedArray); // Table name
$fileLines=file($extractedArray);
    foreach ($fileLines as $line) {
            if(preg_match('/\(all-in\)/i' , $line)) {
                $line = stristr($line, ' (all-in)', true) .', and is all in';
                $allin = ', and is all in';
            }
            else {
                $allin = '';
            }
            if(preg_match('/posts the small blind of \$[\d\.]+/i' , $line)) {
                $player = stristr($line, ' posts ', true);
                $betValue = substr(stristr($line, '$'), 1);
                $bettingMatrix[$player]['betTotal'] = $betValue;
            }
            else if(preg_match('/posts the big blind of \$[\d\.]+/i' , $line)) {
                $player = stristr($line, ' posts ', true);
                $betValue = substr(stristr($line, '$'), 1);
                $bettingMatrix[$player]['betTotal'] = $betValue;
            }
            else if(preg_match('/\S+ raises /i' , $line)) {
                $player = stristr($line, ' raises ', true);
                $betValue = substr(strstr($line, '$'), 1);
                $bettingMatrix[$player]['betTotal'] = $betValue; //total bet this hand (shortcut)
            }
            else if(preg_match('/\S+ bets /i' , $line)) {
                $player = stristr($line, ' bets ', true);
                $betValue = substr(strstr($line, '$'), 1);
                $bettingMatrix[$player]['betTotal'] = $betValue; //total bet this hand (shortcut)
            }
            else if(preg_match('/\S+ calls /i' , $line)) {
                $player = stristr($line, ' calls ', true);
                $betValue = substr(stristr($line, '$'), 1);
                $callValue = $betValue - $bettingMatrix[$player]['betTotal']; //actual amount called
                $bettingMatrix[$player]['betTotal'] = $betValue;
                $line = stristr($line, '$', true)."\$".$callValue.$allin;
                $allin = '';
            }
            else if(preg_match('/(\*\*\* (Flop|Turn|River))|(Full Tilt Poker)/i' , $line)) {
                unset($bettingMatrix); //zero $betValue
            }
            else if(preg_match('/\*\*\* FLOP \*\*\*/i' , $line)) {
                $flop = substr(stristr($line, '['), 0, -2);
                $line = '*** FLOP *** '. $flop;
            }
            else if(preg_match('/\*\*\* TURN \*\*\*/i' , $line)) {
                $turn = substr(stristr($line, '['), 0, -2);
                $line = '*** TURN *** '. $flop .' '. $turn;
            }
            else if(preg_match('/\*\*\* RIVER \*\*\*/i' , $line)) {
                $river = substr(stristr($line, '['), 0, -2);
                $line = '*** RIVER *** '. substr($flop, 0, -1) .' '. substr($turn, 1) .' '. $river;
            }
            else {
            }
        $ourFileHandle = fopen("HH_newest/".$tableName.".txt", 'a') or die("can't open file");
        fwrite($ourFileHandle, $line);
        fclose($ourFileHandle);
    }
}
?>

編集:ここにいる全員が私にくれたヒントに基づいてコードを書き直した後の非常に興味深い結果です。

60 個のテキスト ファイル、合計 5.8 MB

すべての最適化の後 (ループの前に preg->strpos/strstr と $handle を変更): 4 秒。

上記と同じですが、strpos/strstr -> stripos/stristr: 8 秒に変更されました。

上記のように、stripos/stristr を変更 -> preg: 12 秒。

上記のように、ループ内で fopen を変更しました: 180 秒の実行制限後に 45/60 ファイル

完全なスクリプトは次のとおりです。

$fileselection = scandir_recursive('HH_new');
foreach ($fileselection as $extractedArray) {
    $tableName = basename($extractedArray); // Table name
    $handle         = fopen($extractedArray, 'r');
    $ourFileHandle  = fopen("HH_newest/".$tableName.".txt", 'a') or die("can't open file");
    while ($line = fgets($handle)) {
            if (FALSE !== strpos($line, '(all-in)')) {
                $line = strstr($line, ' (all-in)', true) .", and is all in\r\n";
                $allin = ', and is all in';
            } else {
                $allin = '';
            }
            if (FALSE !== strpos($line, ' posts the small blind of $')) {
                $player = strstr($line, ' posts ', true);
                $betValue = substr(strstr($line, '$'), 1);
                $bettingMatrix[$player]['betTotal'] = $betValue;
            }
            else if (FALSE !== strpos($line, ' posts the big blind of $')) {
                $player = strstr($line, ' posts ', true);
                $betValue = substr(strstr($line, '$'), 1);
                $bettingMatrix[$player]['betTotal'] = $betValue;
            }
            else if (FALSE !== strpos($line, ' posts $')) {
                $player = strstr($line, ' posts ', true);
                $betValue = substr(strstr($line, '$'), 1);
                $bettingMatrix[$player]['betTotal'] += $betValue;
            }
            else if (FALSE !== strpos($line, ' raises to $')) {
                $player = strstr($line, ' raises ', true);
                $betValue = substr(strstr($line, '$'), 1);
                $betMade = $betValue - $bettingMatrix[$player]['betTotal']; //actual amount raised by
                $bettingMatrix[$player]['betTotal'] = $betValue; //$line contains total bet this hand (shortcut)
            }
            else if (FALSE !== strpos($line, ' bets $')) {
                $player = strstr($line, ' bets ', true);
                $betValue = substr(strstr($line, '$'), 1);
                $betMade = $betValue - $bettingMatrix[$player]['betTotal']; //actual amount raised by
                $bettingMatrix[$player]['betTotal'] = $betValue; //$line contains total bet this hand (shortcut)
            }
            else if (FALSE !== strpos($line, ' calls $')) {
                $player = strstr($line, ' calls ', true);
                $betValue = substr(strstr($line, '$'), 1);
                $callValue = $betValue - $bettingMatrix[$player]['betTotal']; //actual amount called
                $bettingMatrix[$player]['betTotal'] = $betValue;
                $line = strstr($line, '$', true)."\$".$callValue.$allin. "\r\n";
                $allin = '';
            }
            else if (FALSE !== strpos($line, '*** FLOP ***')) {
                $flop = substr(strstr($line, '['), 0, -2);
                unset($bettingMatrix); //zero $betValue
            }
            else if (FALSE !== strpos($line, '*** TURN ***')) {
                $turn = substr(strstr($line, '['), 0, -2);
                $line = '*** TURN *** '.$flop.' '.$turn."\r\n";
                unset($bettingMatrix); //zero $betValue
            }
            else if (FALSE !== strpos($line, '*** RIVER ***')) {
                $river = substr(strstr($line, '['), 0, -2);
                $line = '*** RIVER *** '. substr($flop, 0, -1) .' '. substr($turn, 1) .' '. $river."\r\n";
                unset($bettingMatrix); //zero $betValue
            }
            else if (FALSE !== strpos($line, 'Full Tilt Poker')) {
                unset($bettingMatrix); //zero $betValue
            }
            else {
            }
        fwrite($ourFileHandle, $line);
    }
    fclose($handle);
    fclose($ourFileHandle);
}
4

4 に答える 4

5

これは、ループ内でファイルを開いたり閉じたりしているためだと思います。 foreach の前に fopen() を移動し、その後に fclose を移動してみてください

于 2009-11-13T16:16:25.657 に答える
4

ここでのファイル書き込みがパフォーマンスの問題ではないかと思います。すべてに対して10個の正規表現を実行しています

strposのような文字列メソッドを使用してサブ文字列を見つけると、処理が高速化される可能性があります。

于 2009-11-13T16:10:24.553 に答える
2

正規表現を廃止すると、最もパフォーマンスが向上します。それらをstrpos()または同様のもの (大文字と小文字を区別しない場合は stripos()) に変更できる場合、速度が向上することに気付くはずです。

見つかった文字列は位置 0 にある可能性があるため、テストは である必要があり'!== false'ます。たとえば、最初のテスト ケースは () のようになります。

if(stripos($line, '(all-in)') !== false) {
    //generate output
}

また、一度にファイル全体を読み取る代わりに fgets() を使用すると、パフォーマンスが向上する場合があります (ただし、これはメモリの問題です)。他の人が述べたように、ループ内のファイルにのみ書き込み、開いたり閉じたりしないでください。

于 2009-11-13T16:15:06.983 に答える
1

これは、かなり役立つはずのいくつかの小さな変更を加えたコードです

  1. file()からに切り替えましたfgets()。これにより、ファイルからすべての行ではなく、一度に 1 行だけがメモリに読み込まれます。
  2. 必要に応じて通話を変更しpreg_match()ましstripos()た。もう少し速くなるはず
  3. の開閉を$ourFileHandle外側のループに移動しました。これにより、ファイルシステムへの stat 呼び出しの数が大幅に減少し、速度が大幅に向上します。

その巨大なif..elseで行うことができる他の多くの最適化がおそらくありますが、私はそれらを別のSOer(またはあなた)に任せます

$fileselection = scandir_recursive('HH_new');
foreach ($fileselection as $extractedArray)
{ 
  $tableName     = basename( $extractedArray ); // Table name
  $handle        = fopen( $extractedArray, 'r' );
  $ourFileHandle = fopen("HH_newest/".$tableName.".txt", 'a') or die("can't open file");

  while ( $line = fgets( $handle ) )
  {
    if ( false !== stripos( $line, '(all-in)' ) )
    {
      $line = stristr($line, ' (all-in)', true) .', and is all in';
      $allin = ', and is all in';
    } else {
      $allin = '';
    }
    if ( preg_match('/posts the small blind of \$[\d\.]+/i' , $line ) )
    {
            $player = stristr($line, ' posts ', true);
            $betValue = substr(stristr($line, '$'), 1);
            $bettingMatrix[$player]['betTotal'] = $betValue;
    }
    else if(preg_match('/posts the big blind of \$[\d\.]+/i' , $line)) {
            $player = stristr($line, ' posts ', true);
            $betValue = substr(stristr($line, '$'), 1);
            $bettingMatrix[$player]['betTotal'] = $betValue;
    }
    else if(preg_match('/\S+ raises /i' , $line)) {
            $player = stristr($line, ' raises ', true);
            $betValue = substr(strstr($line, '$'), 1);
            $bettingMatrix[$player]['betTotal'] = $betValue; //total bet this hand (shortcut)
    }
    else if(preg_match('/\S+ bets /i' , $line)) {
            $player = stristr($line, ' bets ', true);
            $betValue = substr(strstr($line, '$'), 1);
            $bettingMatrix[$player]['betTotal'] = $betValue; //total bet this hand (shortcut)
    }
    else if(preg_match('/\S+ calls /i' , $line)) {
            $player = stristr($line, ' calls ', true);
            $betValue = substr(stristr($line, '$'), 1);
            $callValue = $betValue - $bettingMatrix[$player]['betTotal']; //actual amount called
            $bettingMatrix[$player]['betTotal'] = $betValue;
            $line = stristr($line, '$', true)."\$".$callValue.$allin;
            $allin = '';
    }
    else if(preg_match('/(\*\*\* (Flop|Turn|River))|(Full Tilt Poker)/i' , $line)) {
            unset($bettingMatrix); //zero $betValue
    }
    else if ( FALSE !== stripos( $line, '*** FLOP ***' ) )
    {
            $flop = substr(stristr($line, '['), 0, -2);
            $line = '*** FLOP *** '. $flop;
    }
    else if ( FALSE !== stripos( $line, '*** TURN ***' ) )
    {
            $turn = substr(stristr($line, '['), 0, -2);
            $line = '*** TURN *** '. $flop .' '. $turn;
    }
    else if ( FALSE !== stripos( $line, '*** RIVER ***' ) )
    {
            $river = substr(stristr($line, '['), 0, -2);
            $line = '*** RIVER *** '. substr($flop, 0, -1) .' '. substr($turn, 1) .' '. $river;
    }
    else {
    }
    fwrite($ourFileHandle, $line);
  }
  fclose( $handle );
  fclose( $ourFileHandle );
}
于 2009-11-13T16:36:14.290 に答える