2009-03-08 13 views
9

मैं PHP में Gnu Find ("ढूंढें") को दोहराने की कोशिश कर रहा हूं, लेकिन इसकी गति के करीब भी असंभव लगता है। PHP कार्यान्वयन कम से कम दो बार खोजने के समय का उपयोग करते हैं। PHP के साथ ऐसा करने के तेज तरीके हैं?PHP में रिकर्सिव फ़ाइल स्कैन को गति देना संभव है?

संपादित करें: मैं एक कोड उदाहरण एसपीएल कार्यान्वयन का उपयोग जोड़ा - अपने प्रदर्शन पुनरावृत्ति दृष्टिकोण

EDIT2 के बराबर है: जब 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); 
} 
+0

संभवतः नहीं के लिए PHP मैनुअल टिप्पणियों से कोड पर निम्नलिखित कोड आधारित किया है। PHP उच्च स्तर है और शायद गति के संदर्भ में जीएनयू फाइंड (जिसे शायद सी में लिखा गया है) जैसे कुछ मेल नहीं खाएगा। इसके अलावा, यह रिकर्सन में कुख्यात रूप से धीमा है। उदाहरण के लिए –

+1

+1 उदाहरण के लिए – buggedcom

उत्तर

3

PHP केवल सी, सादा और सरल के रूप में तेज़ प्रदर्शन नहीं कर सकता है।

1

आप एन निर्देशिका रख रहे हैं खुले धाराओं जहां एन निर्देशिका पेड़ की गहराई है। इसके बजाए, एक बार में एक संपूर्ण निर्देशिका की प्रविष्टियों को पढ़ने का प्रयास करें, और फिर प्रविष्टियों पर फिर से प्रयास करें। कम से कम आप डेस्क I/O कैश का उपयोग अधिकतम कर देंगे।

4

मुझे यकीन नहीं है कि प्रदर्शन बेहतर है, लेकिन आप अपने कोड को सरल बनाने के लिए एक रिकर्सिव निर्देशिका इटरेटर का उपयोग कर सकते हैं ... RecursiveDirectoryIterator और 'SplFileInfo` देखें।

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

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

अच्छी सलाह (हालांकि यह बेहतर प्रदर्शन नहीं किया)। – neu242

2

आप व्याख्या किए गए PHP कोड को संकलित सी संस्करण के रूप में तेज़ी से क्यों उम्मीद करेंगे? धीमी गति से केवल दोगुना होना वास्तव में बहुत अच्छा है।

एकमात्र सलाह के बारे में मैं जोड़ना चाहता हूं शुरुआत में ob_start() और ob_get_contents(), ob_end_clean() अंत में करना है। गति चीजें हो सकती है।

+0

हां, उतना ही अच्छा आशावादी होगा :) आउटपुट बफरिंग, मदद से नहीं ... – neu242

4

कुछ भी बदलने शुरू करने से पहले, अपना कोड प्रोफ़ाइल दें।

धीमे हिस्सों कहां से पता लगाने के लिए Xdebug (साथ ही एक सुंदर ग्राफ के लिए kcachegrind) का उपयोग करें। यदि आप चीजों को अंधेरे में बदलना शुरू करते हैं, तो आप कहीं भी नहीं पाएंगे।

मेरी केवल अन्य सलाह पहले से ही तैनात रूप में एसपीएल निर्देशिका iterators का प्रयोग है। आंतरिक सी कोड को काम करना लगभग हमेशा तेज होता है।

0

आप शायद जीएनयू ढूंढने का गंभीरता से विचार करना चाहें। यदि वह उपलब्ध हो और सेफ़ मोड, तो आप शायद परिणाम ठीक तरह हूँ चालू नहीं है:

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

लेकिन वहाँ हो सकता है कुछ निर्देशिका है कि इतना बड़ा है होने के लिए आपको परेशान करने के लिए चाहते हैं के लिए नहीं जा रहे हैं इसके साथ या तो। अन्य तरीकों से धीमेपन को कम करने पर विचार करें। सत्र में निर्देशिका स्टैक को सहेजकर आपकी दूसरी कोशिश को चेकपॉइंट किया जा सकता है (उदाहरण के लिए)। यदि आप उपयोगकर्ता को फ़ाइलों की एक सूची दे रहे हैं, तो बस पृष्ठ को पृष्ठ 2 के लिए सत्र में शेष राज्य को सहेजें।

+0

इस तरह की खोज उपयोगिता को एम्बेड करते समय, प्रदर्शन वास्तव में PHP के प्रदर्शन से भी बदतर है। मुझे लगता है मुझे संतुष्ट होना चाहिए :) – neu242

+0

escapeshellarg और shell_exec – troelskn

0

के रूप में जेसन कोहेन ने सुझाव दिया है, एक बार में एक पूरी सूची पढ़ने के लिए scandir() का उपयोग करें।मैंने 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"; 
} 
संबंधित मुद्दे