문제

나는 복제하려고 노력했다 GNU 찾기 ( "찾기.") PHP에서는 속도에 가까워지는 것은 불가능 해 보입니다. PHP 구현은 찾기 시간의 두 배 이상을 사용합니다. PHP로 더 빠른 방법이 있습니까?

편집 : SPL 구현을 사용하여 코드 예제를 추가했습니다. 성능은 반복적 인 접근 방식과 같습니다.

edit2 : PHP에서 찾기를 호출 할 때 실제로 기본 PHP 구현보다 느 렸습니다. 나는 내가 가진 것에 만족해야한다고 생각한다 :)

// measured to 317% of gnu find's speed when run directly from a shell
function list_recursive($dir) { 
  if ($dh = opendir($dir)) {
    while (false !== ($entry = readdir($dh))) {
      if ($entry == '.' || $entry == '..') continue;

      $path = "$dir/$entry";
      echo "$path\n";
      if (is_dir($path)) list_recursive($path);       
    }
    closedir($d);
  }
}

// measured to 315% of gnu find's speed when run directly from a shell
function list_iterative($from) {
  $dirs = array($from);  
  while (NULL !== ($dir = array_pop($dirs))) {  
    if ($dh = opendir($dir)) {    
      while (false !== ($entry = readdir($dh))) {      
        if ($entry == '.' || $entry == '..') continue;        

        $path = "$dir/$entry";        
        echo "$path\n";        
        if (is_dir($path)) $dirs[] = $path;        
      }      
      closedir($dh);      
    }    
  }  
}

// measured to 315% of gnu find's speed when run directly from a shell
function list_recursivedirectoryiterator($path) {
  $it = new RecursiveDirectoryIterator($path);
  foreach ($it as $file) {
    if ($file->isDot()) continue;

    echo $file->getPathname();
  }
}

// measured to 390% of gnu find's speed when run directly from a shell
function list_gnufind($dir) { 
  $dir = escapeshellcmd($dir);
  $h = popen("/usr/bin/find $dir", "r");
  while ('' != ($s = fread($h, 2048))) {
    echo $s;
  }
  pclose($h);
}
도움이 되었습니까?

해결책

PHP는 C만큼 빠르게 수행 할 수 없습니다.

다른 팁

성능이 더 나은지 확실하지 않지만 재귀 디렉토리 반복자를 사용하여 코드를 더 간단하게 만들 수 있습니다 ... RecursiveDirectoryIterator 그리고 'splfileinfo'.

$it = new RecursiveDirectoryIterator($from);
foreach ($it as $file)
{
    if ($file->isDot())
        continue;

    echo $file->getPathname();
}

무엇이든 변경하기 전에 코드를 프로필하십시오.

같은 것을 사용하십시오 xdebug 느린 부품이 어디에 있는지 알아 내기 위해 (예쁜 그래프를위한 kcachegrind). 맹목적으로 변화를 시작하면 아무데도 가지 않을 것입니다.

저의 다른 조언은 이미 게시 된대로 SPL 디렉토리 반복자를 사용하는 것입니다. 내부 C 코드가 작업을 수행하도록하는 것이 거의 항상 더 빠릅니다.

해석 된 PHP 코드가 컴파일 된 C 버전의 FIND만큼 빠르기를 기대하는 이유는 무엇입니까? 두 배나 느리는 것은 실제로 꽤 좋습니다.

내가 추가 할 유일한 조언은 시작시 OB_START ()를 수행하는 것입니다. 저것 ~할 것 같다 속도를 높이십시오.

N 디렉토리 스트림을 열고 N이 디렉토리 트리의 깊이 인 곳에서 유지하고 있습니다. 대신, 한 번에 전체 디렉토리의 항목을 읽은 다음 항목을 반복하십시오. 최소한 책상 I/O 캐시의 사용을 최대화 할 수 있습니다.

GNU 찾기를 사용하는 것만 진지하게 고려할 수 있습니다. 사용할 수 있고 안전 모드가 켜지지 않으면 결과가 괜찮을 것입니다.

function list_recursive($dir) { 
  $dir=escapeshellcmd($dir);
  $h = popen("/usr/bin/find $dir -type f", "r")
  while ($s = fgets($h,1024)) { 
    echo $s;
  }
  pclose($h);
}

그러나 너무 큰 디렉토리가있을 수 있습니다. 당신은 이것을 귀찮게하고 싶지 않을 것입니다. 다른 방식으로 속도를 상각하는 것을 고려하십시오. 두 번째 시도는 세션에서 디렉토리 스택을 저장하여 확인할 수 있습니다 (예를 들어). 사용자에게 파일 목록을 제공하는 경우 Pageful을 수집 한 다음 2 페이지의 세션에서 나머지 상태를 저장하십시오.

사용해보십시오 scandir() Jason Cohen이 제안한 것처럼 전체 디렉토리를 한 번에 읽으십시오. PHP 매뉴얼 주석의 코드에 대한 다음 코드를 기반으로합니다. scandir()

 function scan( $dir ){
        $dirs = array_diff( scandir( $dir ), Array( ".", ".." ));
        $dir_array = Array();
        foreach( $dirs as $d )
            $dir_array[ $d ] = is_dir($dir."/".$d) ? scan( $dir."/".$d) : print $dir."/".$d."\n";
 }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top