Xhprof का उपयोग करते हुए मैंने देखा कि file_scan_directory()
फ्रंट पेज लोड होने पर निष्पादित करने में 10 सेकंड से अधिक समय लगता है। इसमें इतना समय क्यों लगना चाहिए?
यह xhprofile का आउटपुट है:
Xhprof का उपयोग करते हुए मैंने देखा कि file_scan_directory()
फ्रंट पेज लोड होने पर निष्पादित करने में 10 सेकंड से अधिक समय लगता है। इसमें इतना समय क्यों लगना चाहिए?
यह xhprofile का आउटपुट है:
जवाबों:
ऐसा लगता है कि आप 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 ()) जोड़ें, जो आपको यह बताएं कि कौन सी फ़ाइल यह नहीं ढूंढ रही है।
इस समस्या के उत्पन्न होने के कई कारण हो सकते हैं, और मेरे बड़े निराशाजनक होने के कारण, मैं अब स्वयं को उन कारणों के बारे में कुछ हद तक जानकार पाता हूँ। निराशा की बात है, अगर आपने ड्रुपल कोर को 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
, पैच लागू किया गया था, और व्यापार में वापस आ गया था।
मेरे पास एक समान मुद्दा file_scan_directory()
था - साइट को मार रहा था । प्रत्येक कैश फ़्लश स्कैन किया जा रहा था के node_modules
लिए मेरे कस्टम विषय के भीतर एम्बेडेड एक huuge फ़ोल्डर बदल जाता है gulp
। इन फ़ाइलों को थीम फ़ोल्डर से बाहर ले जाना (और मेरे गलफिले में कुछ रास्तों को अपडेट करना) मेरे लिए इसे ठीक करने के लिए लग रहा था। वैकल्पिक रूप से: मुझे लगता है कि आप हैक कर सकते हैं file.inc
:
'nomask' => '/(\.\.?|CVS|node_modules)$/', // https://www.drupal.org/node/2329453#comment-9360519
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 कैश किया जाना चाहिए ।