file_scan_directory () को निष्पादित करने में लगभग 10 सेकंड लगते हैं


10

Xhprof का उपयोग करते हुए मैंने देखा कि file_scan_directory()फ्रंट पेज लोड होने पर निष्पादित करने में 10 सेकंड से अधिक समय लगता है। इसमें इतना समय क्यों लगना चाहिए?

यह xhprofile का आउटपुट है:

स्क्रीनशॉट


आप "फ्रंट पेज" "file_scan_directory" नहीं कर सकते, क्योंकि फ्रंट पेज एक डेटाबेस टेबल में एक प्रविष्टि है, न कि फाइल-सिस्टम पथ।
लेटेरियन

@Letharion मुझे लगता है कि आपने मेरे सवाल को गलत समझा है। मेरा मतलब है कि जब यह कार्य होता है तो फ्रंट पेज लोड होता है। मैंने प्रश्न संपादित किया।
हकीक

क्या फ्रंट पेज का वास्तव में कुछ खास समय लेने वाले फंक्शन से कोई लेना-देना नहीं है? आप वास्तव में किस निर्देशिका को स्कैन कर रहे हैं? निर्देशिका में क्या है?
लेटेरियन

अहा! मुझे लगा कि आपने स्वयं ही इस समारोह को बुलाया, और सोचा कि आपने अधिक विवरण क्यों नहीं दिया। बर्दिर का जवाब बहुत ही उचित लगता है। :)
लेटेरियन

जवाबों:


14

ऐसा लगता है कि आप Drupal 7 में एक ज्ञात समस्या से प्रभावित हैं ।

सबसे अधिक, आप तब मार रहे हैं जब कई मॉड्यूल गायब हो रहे हैं तब मॉड्यूल पुन: स्कैनिंग से बचें । यह तब होता है जब आपके इंस्टॉलेशन में कुछ गायब मॉड्यूल होते हैं। अपने सिस्टम तालिका की जाँच करने का प्रयास करें:

SELECT name, filename FROM system WHERE type = 'module' AND status = 1 ORDER BY filename

और किसी भी मॉड्यूल को साफ करना जो अभी भी सक्षम है लेकिन फाइल सिस्टम से गायब है।

कुल मिलाकर, Drupal 7 अधिक संसाधन के अनुकूल और स्केलेबल है, तो Drupal 6, इस तरह के कुछ दुर्भाग्यपूर्ण रजिस्टरों के अलावा।

उन कार्यों को देखते हुए, ऐसा लगता है कि यह एक मॉड्यूल या शायद एक मॉड्यूल की एक भी फाइल गायब है। Drupal_get_filename () पर एक नज़र डालें , यह drupal_system_listing () को कॉल करता है, जो इस फ़ंक्शन को कॉल करता है यदि यह अनुरोधित फ़ाइल नहीं ढूँढ सकता है। Drupal_system_listing () कॉल करने से ठीक पहले एक dpm (func_get_args ()) जोड़ें, जो आपको यह बताएं कि कौन सी फ़ाइल यह नहीं ढूंढ रही है।


नहीं। दुर्भाग्य से (!) कोई भी सिस्टम फाइल सिस्टम से गायब नहीं है
hknik

फिर आपको ट्रेस की जरूरत है कि कॉल कहां से आ रही है, हो सकता है कि कोई कस्टम या कंट्रिब मॉड्यूल कुछ गलत कर रहा हो। File_scan_directory () के मूल कार्यों के माध्यम से क्लिक करें और मूल कार्यों की सूची के साथ प्रारंभिक पोस्ट को अपडेट करें।
बेर्दिर

उन कार्यों को देखते हुए, ऐसा लगता है कि यह एक मॉड्यूल या शायद एक मॉड्यूल की एक भी फाइल गायब है। Drupal_get_filename: api.drupal.org/api/drupal.includes .bootstrap.inc/ function/… पर एक नजर डालें । यह फ़ंक्शन को कॉल करता है यदि यह अनुरोधित फ़ाइल नहीं पा सकता है। Drupal_system_listing () कॉल करने से ठीक पहले एक dpm (func_get_args ()) जोड़ें, जो आपको बताएं कि यह कौन सा फ़ंक्शन है जो नहीं मिल रहा है।
बेरदीर

@Berdir आपकी अंतिम टिप्पणी आपके उत्तर में होनी चाहिए, क्योंकि यह प्रासंगिक है।
kiamlaluno

"ड्रुपल 7 में ज्ञात समस्या" और "रिस्कनिंग मॉड्यूल निर्देशिका से बचें" के लिंक टूट गए हैं। दोनों पूर्व स्टेक्सचेंज उत्तर हैं। क्या किसी के पास अन्य संदर्भ हैं?
रफय

4

इस समस्या के उत्पन्न होने के कई कारण हो सकते हैं, और मेरे बड़े निराशाजनक होने के कारण, मैं अब स्वयं को उन कारणों के बारे में कुछ हद तक जानकार पाता हूँ। निराशा की बात है, अगर आपने ड्रुपल कोर को 7.33+ में अपग्रेड करने के बाद इस समस्या पर ध्यान दिया है, तो यह किसी भी मॉड्यूल में एक टाइपो हो सकता है, भले ही आपने उस मॉड्यूल को अपग्रेड न किया हो।

कोड बेस से हटाए गए मॉड्यूल

आप पहले ज्ञात बग की जांच करना चाह सकते हैं, जिसमें @Berdir का उल्लेख है, खासकर यदि आप हाल ही में कोड आधार से "अप्रयुक्त" मॉड्यूल निकाल रहे हैं। यह पता लगाने के लिए कि क्या आपके पास ऐसे मॉड्यूल हैं जो सक्षम हैं, लेकिन फाइल सिस्टम से हटा दिए गए हैं, आप एक स्क्रिप्ट चला सकते हैं जैसे कि यहां बताया गया है - या मेरा उपयोग करें, जो कि ड्रश के साथ एक सिस्टम पर एक मल्टी-साइट इंस्टॉल के लिए लिखा जाए, चलाने के लिए Drupal आधार निर्देशिका से:

find sites -maxdepth 1 -iname '*.*' -type d | sed -rne 's:sites/(.+):echo \1; drush @\1 sqlq "select filename from system where status = 1" | grep "/" | sed -rne "s_(.+)_test -f \\1 || echo \\1_p" | bash:p' | bash

या निम्नलिखित:

while read -r file; do [ -f "$file" ] || echo "$file is missing."; done < <(drush sqlq "SELECT filename FROM system WHERE status = 1")

यदि आपको एक मॉड्यूल मिलता है जिसे कोड बेस से हटा दिया गया है, तो @Berdir द्वारा बताई गई समस्याओं में निर्देशों का पालन करें।

कोडिंग त्रुटियां

यदि ऐसा नहीं है, तो आपकी स्थिति एक कोडिंग त्रुटि के कारण होने की संभावना है, जैसे कि एक फ़ाइल जो हटा दी गई है, लेकिन अभी भी एक drupal_add_js कॉल द्वारा जोड़ा जा रहा है (टिप्पणी # 1928 में समस्या # 1082892) या किसी मॉड्यूल या विषय में एक दुर्भाग्यपूर्ण टाइपो , उदा। imagecache_actions(देखें https://drupal.org/node/2381357 )।

किसी भी स्थिति में, यह पता लगाने के लिए कि ऐसा क्यों हो रहा है, आपको यह जानने की आवश्यकता है कि कौन सी फाइल ड्रुपल को नहीं मिल रही है। तो, Berdir की टिप्पणी के अनुसार, आप अस्थायी रूप से हैक कर सकते हैं drupal_get_filenameमें bootstrap.incसिर्फ करने के लिए कॉल करने से पहले एक लॉग या संदेश कॉल जोड़कर drupal_system_listing()। यदि आपके पास डेवेल मॉड्यूल स्थापित है तो dpmकाम करेगा; यदि नहीं, तो आप उपयोग drupal_set_messageया syslog कर सकते हैं । उदाहरण:

dpm(func_get_args());
drupal_set_message(implode(', ', func_get_args()));
syslog(LOG_WARNING, implode(', ', func_get_args()));

एक बार जब आप जानते हैं कि द्रुपाल क्या देख रहा है, तो यह एक अच्छी शर्त है कि आप यह पता लगाने में सक्षम होंगे कि वहाँ से कहाँ जाना है। गैर-मौजूद मॉड्यूल से एक फ़ाइल शामिल करने के लिए मेरी समस्या एक कॉल के कारण हुई थी imagcache_actions(टाइपो पर ध्यान दें)। इसलिए, मैंने imagecache_actionsअपने कोडबेस (जैसे grep -r imagcache_actions .) में खोज की, और पाया कि imagecache_canvasactions.moduleकिसी भी फ़ंक्शन कॉल के बाहर मॉड्यूल_लोड_किसी भी प्रकार का 1.4 संस्करण , फ़ाइल स्कोप में, टाइपो के साथ है। फिर, इस त्रुटि को केवल Drupal 7.33+ में अपडेट करने के बाद उजागर किया गया था। मैंने पाया कि एक मुद्दा पहले से ही बनाया गया था imagecache_actions, पैच लागू किया गया था, और व्यापार में वापस आ गया था।


2

मेरे पास एक समान मुद्दा file_scan_directory()था - साइट को मार रहा था । प्रत्येक कैश फ़्लश स्कैन किया जा रहा था के node_modulesलिए मेरे कस्टम विषय के भीतर एम्बेडेड एक huuge फ़ोल्डर बदल जाता है gulp। इन फ़ाइलों को थीम फ़ोल्डर से बाहर ले जाना (और मेरे गलफिले में कुछ रास्तों को अपडेट करना) मेरे लिए इसे ठीक करने के लिए लग रहा था। वैकल्पिक रूप से: मुझे लगता है कि आप हैक कर सकते हैं file.inc:

'nomask' => '/(\.\.?|CVS|node_modules)$/', // https://www.drupal.org/node/2329453#comment-9360519


0

file_scan_directory()एक पुनरावर्ती समारोह जो कि किसी दिए गए निर्देशिका के लिए मेल खाते हैं सभी फाइलों है। यह उपयोग is_dir()और opendir()PHP कॉल है जो I / O सिस्टम कॉल के संदर्भ में सबसे अधिक समय तक महंगा हो सकता है। सरल ड्रुपल बूटस्ट्रैप (जैसे time drush ev "") file_scan_directoryकुछ हजारों बार (आपके ड्रुपल फ़ोल्डर पदानुक्रम की जटिलता पर निर्भर करता है, उदाहरण के लिए मॉड्यूल और उसके फ़ोल्डर्स की संख्या ) पर कॉल कर सकते हैं ।

मेरे मामले में मैं ~ 1500 कॉल किया था file_scan_directoryसे कुल मिलकर 2 कॉल में (24 सेकंड drupal_system_listingमें common.inc, तो अन्य कॉल करने के लिए पुनरावर्ती कॉल द्वारा विभाजित थे file_scan_directoryयह आत्म।

आई / ओ कॉल पर प्रदर्शन को बेहतर बनाने के लिए, आपको फ़ाइल कैशिंग को लागू करने की आवश्यकता है। यह OPCache ( opcache.enable=1) को स्थापित और सक्षम करके और इसकी सेटिंग्स को ट्विस्ट करके प्राप्त किया जा सकता है (देखें: PHP OPCache का उपयोग कैसे करें )। मेमोरी-आधारित कैशिंग जैसे कि मेमकेड / रेडिस का उपयोग करने की भी सलाह दी जाती है।

कमांड-लाइन इंटरफ़ेस (जैसे drush) का उपयोग करते समय , आपको सक्षम होना चाहिए opcache.enable_cli=1

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

उदाहरण के लिए

  • लिनक्स का उपयोग करने पर strace(हिट Ctrl- Cसमाप्त करने के लिए):

    sudo strace -c -fp $(pgrep -n php)
  • यूनिक्स का उपयोग करके dtrace( PHP के DTrace स्टेटिक प्रोब का उपयोग करके ), उदा

    sudo dtrace -n 'inline string NAME = "php"; syscall:::entry /(NAME == strstr(NAME, execname)) || (execname == strstr(execname, NAME))/ { @num[probefunc] = count(); }'

आप आगे स्थैतिक कैश को लागू करके drupal_system_listing()या अनुकूलन करके विचार कर सकते हैंfile_scan_directory()

--- a/includes/file.inc
+++ b/includes/file.inc
@@ -2104,6 +2104,8 @@ function file_download_access($uri) {
  *   'filename', and 'name' members corresponding to the matching files.
  */
 function file_scan_directory($dir, $mask, $options = array(), $depth = 0) {
+  static $dirs = array();
+
   // Merge in defaults.
   $options += array(
     'nomask' => '/(\.\.?|CVS)$/',
@@ -2120,7 +2122,12 @@ function file_scan_directory($dir, $mask, $options = array(), $depth = 0) {
       if (!preg_match($options['nomask'], $filename) && $filename[0] != '.') {
         $uri = "$dir/$filename";
         $uri = file_stream_wrapper_uri_normalize($uri);
-        if (is_dir($uri) && $options['recurse']) {
+
+        if (empty($dirs[$uri])) {
+          $dirs[$uri] = is_dir($uri);
+        }
+
+        if ($dirs[$uri] && $options['recurse']) {
           // Give priority to files in this folder by merging them in after any subdirectory files.
           $files = array_merge(file_scan_directory($uri, $mask, $options, $depth + 1), $files);

या file_scan_directoryसे कॉल की कैशिंग के लिए drupal_system_listing(), तो निम्न उपलब्ध पैच की जाँच करें: file_scan_directory कैश किया जाना चाहिए

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.