2009-06-10 12 views
2

この最初のスクリプトは、AJAXリクエストを介して各ユーザーごとに複数回呼び出されます。別のサーバー上の別のスクリプトを呼び出して、テキストファイルの最後の行を取得します。それはうまく動作しますが、改善の余地はたくさんあると思いますが、私は非常に良いPHPコーダーではないので、スピードと効率のためにこれを最適化することができるコミュニティの助けを得たいと期待しています:この単純なPHPスクリプトを最適化するにはどうすればよいですか?

AJAXこのスクリプト

<?php session_start(); 
$fileName = $_POST['textFile']; 
$result = file_get_contents($_SESSION['serverURL']."fileReader.php?textFile=$fileName"); 
echo $result; 
?> 

に行われたPOSTリクエストは、それはテキストファイル

<?php 
$fileName = $_GET['textFile']; 
if (file_exists('text/'.$fileName.'.txt')) { 
    $lines = file('text/'.$fileName.'.txt'); 
    echo $lines[sizeof($lines)-1]; 
} 
else{ 
    echo 0; 
} 
?> 

を読み込み、この外部スクリプトにGETリクエストは、私はすべての時間をいただければ幸いますエル・P。私は、最初のスクリプトで行うことができるより多くの改善があると思います。それは高価な関数呼び出し(file_get_contents)を作成する、少なくとも私はその高価だと思います!

+0

私はそれが動作しますので、それは何も問題はありませんけど、私はただ、このスクリプトは、倍の10,000秒と呼ばれるようにそれを改善しようとしています。 :) – Abs

答えて

1

このスクリプトは、返すために起こっている場所とファイルの種類を制限する必要があります。

これをしようとして誰かを考える:

http://www.yoursite.com/yourscript.php?textFile=../../../etc/passwd(または類似したもの)

遅延が発生する場所を探してみてください。.. HTTPリクエストは、長い時間がかかるん、またはファイルが読み込み、それがかかるほど大きく、長いです。

リクエストが遅い場合は、結果をローカルにキャッシュしてみてください。

ファイルが巨大な場合は、ファイルの最後の行を定期的に(またはすべての変更時に)抽出し、他のスクリプトが直接アクセスできるファイルに保存するcronジョブを設定できます。

0

ファイルが変更されていない場合は、最後の行をキャッシュする必要があります。

ファイルが変更されていて、ファイルの作成方法を制御している場合は、その行が読み込まれる頻度に応じて、その行が書き換えられる可能性があります。

編集:

サーバーには、それは、そのログに書き込むmemcacheの中でそれを置くために望んでいるかを把握して、ログにそれを書くことができます。最後の行の要求は、ファイルの読み込みではなく、memcacheを使って行うことができます。

+0

ええ、ファイルは常に変化しています。私は最後のアイデアが好きで、行の順序を逆にするので、最初の行だけを取得します。私は得ることができるパフォーマンスのあらゆる少しの利益が必要です! – Abs

1

readfileは、ここにあなたの友人です ディスク上のファイルを読み取り、それをクライアントにストリームします。

スクリプト1:

<?php 
    session_start(); 
    // added basic argument filtering 
    $fileName = preg_replace('/[^A-Za-z0-9_]/', '', $_POST['textFile']); 

    $fileName = $_SESSION['serverURL'].'text/'.$fileName.'.txt'; 
    if (file_exists($fileName)) { 

     // script 2 could be pasted here 

     //for the entire file 
     //readfile($fileName); 

     //for just the last line 
     $lines = file($fileName); 
     echo $lines[count($lines)-1]; 


     exit(0); 
    } 

    echo 0; 
?> 

このスクリプトは、さらに、それにキャッシュを追加することによって向上させることができました。しかしそれはもっと複雑です。 非常にの基本キャッシングが可能です。

スクリプト2:

<?php 

    $lastModifiedTimeStamp filemtime($fileName); 

    if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { 
     $browserCachedCopyTimestamp = strtotime(preg_replace('/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE'])); 
     if ($browserCachedCopyTimestamp >= $lastModifiedTimeStamp) { 
      header("HTTP/1.0 304 Not Modified"); 
      exit(0); 
     } 
    } 

    header('Content-Length: '.filesize($fileName)); 
    header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T', time() + 604800)); // (3600 * 24 * 7) 
    header('Last-Modified: '.date('D, d M Y H:i:s \G\M\T', $lastModifiedTimeStamp)); 
?> 
+0

クライアントが最後の行だけを必要とするなら、それを使うべきですか? – Abs

+0

'スクリプト1'は2つのスクリプトを置き換えます。 readfile()はファイル全体を読み込んでブラウザに送ります。もしわからないのであれば、「スクリプト2」を忘れてください – Jacco

+0

file_existsはリモートファイル(URL)で動作しますか? – Abs

0

最初のものがまずあります。それを本当に最適化する必要がありますか?それはあなたのユースケースで最も遅いのですか?あなたはそれを確認するためにxdebugを使用しましたか?あなたはそれをやった場合は、上の読み:

あなたが本当に有効に最初のスクリプトを最適化することはできません:あなたは、HTTPリクエストが必要な場合は、HTTPリクエストを必要としています。ただし、可能であれば、http要求をスキップするとパフォーマンスが向上する可能性があります(つまり、最初のスクリプトが2番目のスクリプトが操作する同じファイルにアクセスできる場合)。 2番目のスクリプトについては

:メモリにファイル全体を読むためにはある程度のオーバーヘッドのように見えるが、ファイルが小さい場合には、neglibableあるん。コードは非常に読みやすいように見えますが、私はそのままにしておきます。

ファイルが大きい場合は、しかし、あなたは、遅延の最も可能性の高いソースがクロスサーバHTTPリクエストということですfopen()とその友人fseek()fread()

# Do not forget to sanitize the file name here! 
# An attacker could demand the last line of your password 
# file or similar! ($fileName = '../../passwords.txt') 
$filePointer = fopen($fileName, 'r'); 
$i = 1; 
$chunkSize = 200; 
# Read 200 byte chunks from the file and check if the chunk 
# contains a newline 
do { 
    fseek($filePointer, -($i * $chunkSize), SEEK_END); 
    $line = fread($filePointer, $i++ * $chunkSize); 
} while (($pos = strrpos($line, "\n")) === false); 
return substr($line, $pos + 1); 
+0

あなたの洞察力のある返信をありがとう。私は以前(xdebug)使っていませんでしたが、今私はそれを調べています。私が読み込んだテキストファイルは20行以下で、行の長さは約5/6語です。 – Abs

+0

私はコードに触れません。ループを解釈するオーバーヘッドは、そのサイズのファイルのゲインよりも大きくなる可能性があります:) – soulmerge

+0

ああ、ありがとう! :) – Abs

0

を使用する場合があります。ファイルが小さい場合、fopen/fread/fcloseのコストはHTTP要求全体に比べて何もありません。

(少し前、私は10分の1秒まで秒から遅延を低減し、ローカルファイルの読み取りによって、HTTPリクエストを交換する。dinamicallyイメージベースのメニューを生成するための画像を取得するためにHTTPを使用していました。)私がいることを前提とし

ファイルサーバのファイルシステムに直接アクセスする明白な解決策は問題になりません。そうでなければ、それは最も簡単で簡単なオプションです。

ない場合は、キャッシュを使用することができます。ファイル全体を取得する代わりに、HEADリクエストを発行し、タイムスタンプをローカルコピーと比較するだけです。あなたはAjaxを更新し、同じファイルに基づいてクライアントの多くがある場合

また、あなたは(たとえば、流星)彗星を使用して見て検討するかもしれません。チャットなど、複数のクライアントに1回の変更をブロードキャストする必要がある場合などに使用されます。

関連する問題