2009-03-08 26 views
9

Tôi đã cố gắng sao chép Gnu Find ("tìm") trong PHP, nhưng có vẻ như không thể đạt được tốc độ gần như vậy. Việc triển khai PHP sử dụng ít nhất hai lần thời gian Tìm kiếm. Có cách nào nhanh hơn để làm điều này với PHP?Có thể tăng tốc độ quét tệp đệ quy trong PHP không?

EDIT: Tôi đã thêm một ví dụ mã sử dụng thực hiện SPL - hiệu quả của nó tương đương với phương pháp lặp đi lặp lại

EDIT2: Khi gọi tìm từ PHP nó đã thực sự chậm hơn so với việc thực hiện PHP mẹ đẻ. Tôi đoán tôi nên hài lòng với những gì tôi đã có :)

// 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); 
} 
+0

Có thể là không. PHP là cấp cao và có thể sẽ không bao giờ khớp với thứ gì đó như Gnu Find (có thể được viết bằng C) về mặt tốc độ. Ngoài ra, nó rất nổi tiếng khi đệ quy. –

+1

+1 ví dụ mã số – buggedcom

Trả lời

3

PHP không thể thực hiện nhanh như C, đơn giản và đơn giản.

1

Bạn đang giữ N thư mục suối mở trong đó N là độ sâu của cây thư mục. Thay vào đó, hãy thử đọc toàn bộ giá trị của các mục nhập cùng một lúc và sau đó lặp lại các mục nhập. Ít nhất bạn sẽ tối đa hóa việc sử dụng bộ đệm I/O của bàn làm việc.

4

Tôi không chắc liệu hiệu suất có tốt hơn hay không, nhưng bạn có thể sử dụng trình lặp thư mục đệ quy để làm cho mã của bạn đơn giản hơn ... Xem RecursiveDirectoryIterator'SplFileInfo`.

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

    echo $file->getPathname(); 
} 
+0

Lời khuyên tốt (mặc dù nó không hoạt động tốt hơn). – neu242

2

Tại sao bạn mong đợi mã PHP được giải thích nhanh như phiên bản tìm kiếm đã biên dịch C? Chỉ có hai lần làm chậm thực sự là khá tốt.

Giới thiệu về lời khuyên duy nhất tôi muốn thêm là thực hiện ob_start() ở đầu và ob_get_contents(), ob_end_clean() ở cuối. Điều đó có thể tăng tốc độ.

+0

Có, cũng như tốt sẽ rất lạc quan :) Đầu ra đệm không giúp đỡ, bằng cách này ... – neu242

4

Trước khi bạn bắt đầu thay đổi bất cứ điều gì, cấu hình mã của bạn.

Sử dụng thứ gì đó như Xdebug (cộng với kcachegrind để có biểu đồ đẹp) để tìm hiểu vị trí của các phần chậm. Nếu bạn bắt đầu thay đổi mọi thứ một cách mù quáng, bạn sẽ không đi đâu cả.

Lời khuyên duy nhất khác của tôi là sử dụng trình vòng lặp thư mục SPL như đã đăng. Để cho mã C bên trong làm công việc hầu như luôn luôn nhanh hơn.

0

Bạn có thể muốn xem xét nghiêm túc việc sử dụng GNU. Nếu tính năng này khả dụng và chế độ an toàn không được bật, có thể bạn sẽ thích kết quả tốt:

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); 
} 

Tuy nhiên, có thể có một số thư mục quá lớn, bạn sẽ không muốn bận tâm với điều này. Cân nhắc phân bổ sự chậm chạp theo những cách khác. Lần thử thứ hai của bạn có thể được kiểm tra (ví dụ) bằng cách đơn giản lưu ngăn xếp thư mục trong phiên. Nếu bạn đang cung cấp cho người dùng danh sách tệp, chỉ cần thu thập một trang rồi lưu phần còn lại của trạng thái trong phiên cho trang 2.

+0

Khi nhúng tiện ích tìm thấy như thế này, hiệu suất thực sự tồi tệ hơn hiệu suất của PHP. Tôi đoán tôi nên hài lòng :) – neu242

+0

escapeshellarg và shell_exec – troelskn

0

Hãy thử sử dụng scandir() để đọc toàn bộ thư mục cùng một lúc, như Jason Cohen đã gợi ý.Tôi đã dựa vào mã sau trên mã từ nhận xét thủ công php cho 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"; 
} 
Các vấn đề liên quan