40

当社のウェブサイトに画像を表示するときは、 を呼び出してファイルが存在するかどうかを確認しますfile_exists()。ファイルが見つからない場合は、ダミー イメージに戻ります。

ただし、プロファイリングでは、これがページ生成の最も遅い部分であり、ファイルごとfile_exists()に最大1/2 ミリ秒かかることが示されています。40 程度のファイルのみをテストしていますが、それでもページの読み込み時間は20ミリ秒かかります。

誰かがこれをより速くする方法を提案できますか? ファイルが存在するかどうかをテストするより良い方法はありますか? ある種のキャッシュを構築する場合、どのように同期を維持する必要がありますか。

4

20 に答える 20

34

file_exists()非常に安価な操作である必要があります。file_existsパフォーマンスを向上させるために独自のキャッシュを構築することにも注意してください。

参照: http://php.net/manual/en/function.file-exists.php

于 2009-11-10T15:32:38.857 に答える
23

絶対パスを使用してください!設定に応じて、include_path相対ファイル パスをチェックすると、PHP はこれらのディレクトリをすべて (!) チェックします。include_path存在を確認する前に一時的に設定を解除することがあります。

realpath()同じことをしますが、速いかどうかはわかりません。

しかし、ファイル アクセス I/O は常に低速です。通常、ハードディスクへのアクセスは、プロセッサで何かを計算するよりも遅くなります

于 2009-11-10T15:31:50.233 に答える
21

ローカル ファイルの存在を確認する最速の方法は、stream_resolve_include_path()です。

if (false !== stream_resolve_include_path($s3url)) { 
  //do stuff 
}

パフォーマンス結果stream_resolve_include_path()file_exists()の比較:

Test name       Repeats         Result          Performance     
stream_resolve  10000           0.051710 sec    +0.00%
file_exists     10000           0.067452 sec    -30.44%

テストでは絶対パスを使用しました。テストソースはこちら. PHP のバージョン:

PHP 5.4.23-1~dotdeb.1 (cli) (ビルド: 2013 年 12 月 13 日 21:53:21)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0、Copyright (c) 1998-2013 Zend Technologies

于 2014-01-01T07:00:35.837 に答える
11

ファイルが見つからない場合は、ダミー イメージにフォールバックします

このダミー イメージにフォールバックすることにのみ関心がある場合は、file-not-found で (ダミー イメージへの) リダイレクトを使用して、クライアントがサーバーとネゴシエートできるようにすることを検討してください。

そうすれば、クライアント側でわずかなリダイレクト オーバーヘッドと目立たない遅延が発生するだけです。少なくとも、「高価な」(そうではないことはわかっています)への呼び出しを取り除くことができますfile_exists

ちょっとした考え。

于 2009-11-10T15:43:17.860 に答える
7

PHP 5.6 でのベンチマーク:

既存のファイル:

0.0012969970 : stream_resolve_include_path + include  
0.0013520717 : file_exists + include  
0.0013728141 : @include  

無効なファイル:

0.0000281333 : file_exists + include  
0.0000319480 : stream_resolve_include_path + include  
0.0001471042 : @include  

無効なフォルダ:

0.0000281333 : file_exists + include  
0.0000360012 : stream_resolve_include_path + include  
0.0001239776 : @include  

コード:

// microtime(true) is less accurate.
function microtime_as_num($microtime){
  $time = array_sum(explode(' ', $microtime));
  return $time;
}

function test_error_suppression_include ($file) {
  $x = 0;
  $x = @include($file);
  return $x;
}

function test_file_exists_include($file) {
  $x = 0;
  $x = file_exists($file);
  if ($x === true) {
    include $file;
  }
  return $x;
}

function test_stream_resolve_include_path_include($file) {
  $x = 0;
  $x = stream_resolve_include_path($file);
  if ($x !== false) {
    include $file;
  }
  return $x;
}

function run_test($file, $test_name) {
  echo $test_name . ":\n";
  echo str_repeat('=',strlen($test_name) + 1) . "\n";

  $results = array();
  $dec = 10000000000; // digit precision as a multiplier

  $i = 0;
  $j = 0;
  $time_start = 0;
  $time_end = 0;
  $x = -1;
  $time = 0;

  $time_start = microtime();
  $x= test_error_suppression_include($file);
  $time_end = microtime();
  $time = microtime_as_num($time_end) - microtime_as_num($time_start);

  $results[$time*$dec] = '@include';

  $i = 0;
  $j = 0;
  $time_start = 0;
  $time_end = 0;
  $x = -1;
  $time = 0;

  $time_start = microtime();
  $x= test_stream_resolve_include_path_include($file);
  $time_end = microtime();
  $time = microtime_as_num($time_end) - microtime_as_num($time_start);

  $results[$time * $dec] = 'stream_resolve_include_path + include';

  $i = 0;
  $j = 0;
  $time_start = 0;
  $time_end = 0;
  $x = -1;
  $time = 0;

  $time_start = microtime();
  $x= test_file_exists_include($file);
  $time_end = microtime();
  $time = microtime_as_num($time_end) - microtime_as_num($time_start);

  $results[$time * $dec ] = 'file_exists + include';

  ksort($results, SORT_NUMERIC);

  foreach($results as $seconds => $test) {
    echo number_format($seconds/$dec,10) . ' : ' . $test . "\n";
  }
  echo "\n\n";
}

run_test($argv[1],$argv[2]);

コマンドライン実行:

php test.php '/path/to/existing_but_empty_file.php' 'Existing File'  
php test.php '/path/to/non_existing_file.php' 'Invalid File'  
php test.php '/path/invalid/non_existing_file.php' 'Invalid Folder'  
于 2016-08-25T16:47:46.960 に答える
4

ファイルを複数のサブディレクトリに分割するためのハッシュ ルーチンを作成します。

ファイル名.jpg -> 012345 -> /01/23/45.jpg

また、mod_rewrite を使用して、404.

于 2009-11-10T16:14:57.633 に答える
3

file_exists()PHP によって自動的にキャッシュされます。ファイルの存在を確認するためのより高速な関数が PHP にあるとは思えません。

このスレッドを参照してください。

于 2009-11-10T15:32:37.873 に答える
2

何をしたいのか正確にはわかりませんが、クライアントに処理させることができます。

于 2010-07-26T17:03:27.150 に答える
2

既存の のみをチェックする場合はfiles、 を使用しますis_file()file_exists()既存のファイルまたはディレクトリをチェックするためis_file()、少し高速になる可能性があります。

于 2009-11-10T15:51:30.090 に答える
1

それらはすべて同じディレクトリにありますか?もしそうなら、すべての file_exists ルックアップではなく、ファイルのリストを取得してハッシュに保存し、それと比較する価値があるかもしれません。

于 2009-11-10T15:34:27.427 に答える
1

画像ファイルの存在を確認したい場合、はるかに高速な方法はgetimagesizeを使用することです!

ローカルでもリモートでも高速化!

if(!@GetImageSize($image_path_or_url)) // False means no imagefile
 {
 // Do something
 }
于 2015-02-11T10:27:04.067 に答える
0

解決策を探してこのページにたどり着きました.fopenがうまくいくようです. このコードを使用する場合、見つからないファイルのエラー ログを無効にすることができます。

<?php
for ($n=1;$n<100;$n++){
clearstatcache();
$h=@fopen("files.php","r");
if ($h){
echo "F";
fclose($h);
}else{
echo "N";
}
}
?>
于 2014-09-21T20:23:38.203 に答える
0

どうglob()ですか?でも速いかどうかはわかりません。

http://www.php.net/manual/en/function.glob.php

于 2009-11-10T15:37:44.377 に答える
0

1 回の呼び出しで 1/2 ミリ秒というのは非常に手頃な価格だと思います。ファイル関数は、ファイル操作を処理する下位レイヤーに非常に近いため、これよりも高速な代替手段はないと思います。

ただし、結果を memcache または同様の機能にキャッシュする file_exists() のラッパーを作成することもできます。これにより、日常の使用では時間がほぼゼロになるはずです。

于 2009-11-10T15:39:36.347 に答える
0

ファイルをフォルダに保存すると、アップロードが成功した場合、DB テーブルへのパスを保存できます。

次に、要求されたファイルのパスを見つけるためにデータベースにクエリを実行する必要があります。

于 2012-01-26T10:41:38.237 に答える
0

cronjob を実行して、イメージのリストを定期的に作成し、それらを DB/file/BDB/... に保存できます。

30 分ごとでも問題ありませんが、ファイルの追加/削除の場合にキャッシュをリセットするためのインターフェイスを必ず作成してください。

そして、 find の実行も簡単です。-mmin -30 -print0 をシェルで実行し、新しいファイルを追加します。

于 2011-04-19T08:08:17.720 に答える
0

特に認証がある場合は、画像のURLをデータベースに保持し、それをセッション変数に入れるのが最善の方法だと思います。これらの方法では、ページがリロードされるたびにチェックする必要はありません

于 2017-05-09T02:40:53.287 に答える
-1

これがより高速になるかどうかはわかりませんが、それでもベンチマークを行いたいようです:

すべての画像パスの大規模な配列のキャッシュを構築します。

$array = array('/path/to/file.jpg' => true, '/path/to/file2.gif' => true);

要件に応じて、キャッシュを毎時または毎日更新します。これを行うには、 cronを使用して PHP スクリプトを実行します。このスクリプトは、files ディレクトリを再帰的に調べて、パスの配列を生成します。

ファイルが存在するかどうかを確認したい場合は、キャッシュされた配列をロードし、単にisset()チェックを実行して配列のインデックス検索を高速化します。

if (isset($myCachedArray[$imgpath])) {
    // handle display
}

キャッシュの読み込みによるオーバーヘッドはまだありますが、メモリにとどまるのに十分なほど小さくなれば幸いです。ページでチェックしている画像が複数ある場合は、ページの読み込み時にキャッシュを読み込むことができるため、より大きな効果が得られることに気付くでしょう。

于 2009-11-10T15:51:27.353 に答える