Za pomocą xhprof zauważyłem, że wykonanie file_scan_directory()
zajmuje więcej niż 10 sekund po załadowaniu pierwszej strony. Dlaczego miałoby to trwać tak długo?
To jest wynik działania xhprofile:
7
performance
hknik
źródło
źródło
Odpowiedzi:
Wygląda na to, że znany ci problem z Drupal 7 dotyczy Ciebie .
Patrząc na te funkcje, wygląda na to, że brakuje modułu lub może pojedynczego pliku modułu. Spójrz na drupal_get_filename () , wywołuje on drupal_system_listing (), który wywołuje tę funkcję, jeśli nie może znaleźć żądanego pliku. Dodaj dpm (func_get_args ()) tuż przed wywołaniem drupal_system_listing (), co powinno ci powiedzieć, którego pliku nie znajduje.
źródło
Jest kilka powodów, dla których ten problem może powstać, i ku mojemu wielkiemu przerażeniu, teraz mam dość wiedzy na temat tych przyczyn. Frustrujące jest to, że jeśli właśnie zauważyłeś ten problem po aktualizacji rdzenia Drupala do wersji 7.33+, może to być literówka w dowolnym module, nawet jeśli nie zaktualizowałeś tego modułu.
Moduły usunięte z bazy kodu
Możesz najpierw sprawdzić znany błąd, o którym wspomina @Berdir, szczególnie jeśli ostatnio usuwasz „nieużywane” moduły z bazy kodu. Aby dowiedzieć się, czy masz moduły, które są włączone, ale zostały usunięte z systemu plików, możesz uruchomić skrypt, taki jak wymieniony tutaj - lub użyć mojego, napisanego do instalacji w wielu witrynach w systemie z Drush, aby uruchomić z katalogu podstawowego Drupal:
lub następujące:
Jeśli znajdziesz moduł, który został usunięty z bazy kodu, postępuj zgodnie ze wskazówkami w kwestiach wspomnianych przez @Berdir.
Błędy kodowania
Jeśli tak nie jest, Twoja sytuacja jest prawdopodobnie spowodowana błędem kodowania, takim jak plik, który został usunięty, ale nadal jest dodawany przez wywołanie drupal_add_js (od komentarza 19 w numerze # 1082892) lub niefortunną literówkę w module lub motywie , np.
imagecache_actions
(patrz https://drupal.org/node/2381357 ).W każdym razie, aby dokładnie zrozumieć, dlaczego tak się dzieje, musisz dokładnie wiedzieć, którego pliku Drupal nie może znaleźć. Tak więc, zgodnie z komentarzem Berdir użytkownika, można tymczasowo włamać
drupal_get_filename
siębootstrap.inc
przez dodanie do dziennika lub wiadomość wezwanie tuż przed wywołaniemdrupal_system_listing()
. Jeśli masz zainstalowany moduł Devel, todpm
będzie działał; jeśli nie, możesz użyćdrupal_set_message
lub syslog. Przykłady:Gdy dowiesz się, czego szuka Drupal, dobrze jest założyć, że będziesz w stanie dowiedzieć się, dokąd się udać. Mój problem spowodowany był wywołaniem dołączenia pliku z nieistniejącego modułu
imagcache_actions
(zwróć uwagę na literówkę). Tak więc szukałemimagecache_actions
w mojej bazie kodu (np.grep -r imagcache_actions .
) I znalazłem, że wersja 1.4imagecache_canvasactions.module
używa modułu moduł_ładuj_włączenie poza jakimkolwiek wywołaniem funkcji, w zakresie plików, z literówką. Ponownie ten błąd został ujawniony dopiero po aktualizacji do Drupal 7.33+. Odkryłem, że problem został już utworzonyimagecache_actions
, zastosowałem łatkę i wróciłem do pracy.źródło
Miałem bardzo podobny problem -
file_scan_directory()
zabijałem witrynę. Okazuje się, że ogromnynode_modules
folder osadzony w moim niestandardowym motywiegulp
był skanowany przy każdym opróżnieniu pamięci podręcznej. Przeniesienie tych plików z folderu motywu (i zaktualizowanie niektórych ścieżek w moim pliku gulp) wydawało mi się to naprawić. Alternatywnie: Myślę, że możesz zhakowaćfile.inc
:'nomask' => '/(\.\.?|CVS|node_modules)$/', // https://www.drupal.org/node/2329453#comment-9360519
źródło
Jest
file_scan_directory()
to funkcja rekurencyjna, która wszystkie pliki pasujące do danego katalogu. Wykorzystujeis_dir()
iopendir()
wywołuje PHP, które mogą być najdroższe pod względem wywołań systemowych We / Wy. Prosty bootstrap Drupal (np.time drush ev ""
) Może wywoływaćfile_scan_directory
kilka tysięcy razy (w zależności od złożoności hierarchii folderów Drupal, np. Liczby modułów i folderów).W moim przypadku miałem ~ 1500 wywołań
file_scan_directory
(24 sekund w sumie składających się z 2 połączeńdrupal_system_listing
wcommon.inc
, a następnie pozostałe połączenia były podzielone przez rekurencyjnych wywołańfile_scan_directory
to-ja.Aby poprawić wydajność połączeń We / Wy, należy zaimplementować buforowanie plików. Można to osiągnąć, instalując i włączając OPCache (
opcache.enable=1
) oraz dostosowując jego ustawienia (patrz: Jak korzystać z OPCache PHP? ). Zalecane jest również stosowanie buforowania opartego na pamięci, takiego jak memcached / redis.Korzystając z interfejsu wiersza polecenia (takiego jak
drush
), należy również włączyćopcache.enable_cli=1
.Po zmianie możesz sprawdzić bardziej wymagające połączenia systemowe za pomocą dostępnych debuggerów.
Na przykład
W systemie Linux przy użyciu
strace
(naciśnij Ctrl- Caby zakończyć):W systemie Unix
dtrace
(za pomocą statycznych sond DTrace PHP ), npMożesz dalej rozważyć optymalizację
drupal_system_listing()
lubfile_scan_directory()
wdrożenie statycznej pamięci podręcznej, npLub w celu buforowania
file_scan_directory
wywołań zdrupal_system_listing()
, a następnie sprawdź następującą łatkę dostępną pod adresem: katalog_kanału_pliku powinien być buforowany .źródło