Drupal 性能 file_scan_directory/opendir 超过 500 毫秒

Drupal performance file_scan_directory/opendir taking over 500ms

在使用 XHProf 分析 drupal7.34 实例后,我发现 file_scan_dir 调用的 opendir 函数递归到 15 深度,执行时间很长。 file_scan_dir 又被 drupal_system_listing 调用(3 次调用)

Function   Calls  Ex Wall  Wall %
opendir    1608   500ms    27%
ob_flush   1      270ms    17%
is_dir     10,872 107ms     7%
preg_match 20,597  85ms     5%

按键设置

**php.ini (PHP5.3.3)**
memory_limit = 512MB
realpath_cache_size = 1024k
max_execution_time = 90

**apc.ini**
apc.shm_size=192M  (free 100MB after several loads)
apc.stat=1
apc.stat_ctime=0

drupal 文件在 NFS 文件系统上,所以我预计它会有点慢。 当我更改 apc.stat=0 并重新启动 apache 时。我预计 opendir 开销会消失,因为大部分文件将从 opcache 中读取,但这些数字在同一页面多次重新加载后根本不会改变。

我确实检查过我没有丢失模块,这是 drupal 7 的一个已知问题。看起来 drupal 似乎正在搜索一些丢失的文件。

知道是什么导致了这个问题吗?

我是临时加上dpm(func_get_args());才发现问题的在 bootstrap.inc 中讨论 https://drupal.stackexchange.com/a/138345

原来 AT-commerce 版本 7.x-3.0 主题没有正确检查其他可选模块,导致性能严重下降。

此修复在每次页面加载时节省了 900 多毫秒,影响很大

我已经为 drupal 模块提供了一个修复建议 https://www.drupal.org/node/2406089 为了完整起见在此列出

  /**
  * Implements hook_css_alter().
  */
 function at_commerce_css_alter(&$css) {
   // Replace all Commerce module CSS files with our own for total control over all        styles.
   // Commerce module uses the BAT CSS file naming convention (base, admin, theme).
   $path = drupal_get_path('theme', 'at_commerce');


   // cart
   if (module_exists('commerce_cart')){
       $cart_theme = drupal_get_path('module', 'commerce_cart') . '/theme/commerce_cart.   theme.css';
       if (isset($css[$cart_theme])) {
         $css[$cart_theme]['data'] = $path . '/css/commerce/commerce_cart.theme.css';
         $css[$cart_theme]['group'] = 1;
       }
   }


   // checkout
   if (module_exists('commerce_checkout')){
       $checkout_base  = drupal_get_path('module', 'commerce_checkout') . '/theme/         commerce_checkout.base.css';
       $checkout_admin = drupal_get_path('module', 'commerce_checkout') . '/theme/         commerce_checkout.admin.css';
       $checkout_theme = drupal_get_path('module', 'commerce_checkout') . '/theme/         commerce_checkout.theme.css';
       if (isset($css[$checkout_base])) {
         $css[$checkout_base]['data'] = $path . '/css/commerce/commerce_checkout.base.     css';
         $css[$checkout_base]['group'] = 1;
       }
       if (isset($css[$checkout_admin])) {
         $css[$checkout_admin]['data'] = $path . '/css/commerce/commerce_checkout.admin.   css';
         $css[$checkout_admin]['group'] = 1;
       }
       if (isset($css[$checkout_theme])) {
         $css[$checkout_theme]['data'] = $path . '/css/commerce/commerce_checkout.theme.   css';
         $css[$checkout_theme]['group'] = 1;
       }
   }


   // customer
   if (module_exists('commerce_customer')){
       $customer_admin = drupal_get_path('module', 'commerce_customer') . '/theme/         commerce_customer.admin.css';
       if (isset($css[$customer_admin])) {
         $css[$customer_admin]['data'] = $path . '/css/commerce/commerce_customer.admin.   css';
         $css[$customer_admin]['group'] = 1;
       }
   }


   // file (contrib)
   if (module_exists('commerce_file')){
       $file_forms = drupal_get_path('module', 'commerce_file') . '/theme/commerce_file.   forms.css';
       if (isset($css[$file_forms])) {
         $css[$file_forms]['data'] = $path . '/css/commerce/commerce_file.forms.css';
         $css[$file_forms]['group'] = 1;
       }
   }


   // line items
   if (module_exists('commerce_line_item')){
       $line_item_admin = drupal_get_path('module', 'commerce_line_item') . '/theme/       commerce_line_item.admin.css';
       $line_item_theme = drupal_get_path('module', 'commerce_line_item') . '/theme/       commerce_line_item.theme.css';
       if (isset($css[$line_item_admin])) {
         $css[$line_item_admin]['data'] = $path . '/css/commerce/commerce_line_item.admin. css';
         $css[$line_item_admin]['group'] = 1;
       }
       if (isset($css[$line_item_theme])) {
         $css[$line_item_theme]['data'] = $path . '/css/commerce/commerce_line_item.theme. css';
         $css[$line_item_theme]['group'] = 1;
       }
   }


   // order
   if (module_exists('commerce_order')){
       $order_admin = drupal_get_path('module', 'commerce_order') . '/theme/               commerce_order.admin.css';
       $order_theme = drupal_get_path('module', 'commerce_order') . '/theme/               commerce_order.theme.css';
       if (isset($css[$order_admin])) {
         $css[$order_admin]['data'] = $path . '/css/commerce/commerce_order.admin.css';
         $css[$order_admin]['group'] = 1;
       }
       if (isset($css[$order_theme])) {
         $css[$order_theme]['data'] = $path . '/css/commerce/commerce_order.theme.css';
         $css[$order_theme]['group'] = 1;
       }
   }


   // payment
   if (module_exists('commerce_payment')){
       $payment_admin = drupal_get_path('module', 'commerce_payment') . '/theme/           commerce_payment.admin.css';
       $payment_theme = drupal_get_path('module', 'commerce_payment') . '/theme/           commerce_payment.theme.css';
       if (isset($css[$payment_admin])) {
         $css[$payment_admin]['data'] = $path . '/css/commerce/commerce_payment.admin.     css';
         $css[$payment_admin]['group'] = 1;
       }
       if (isset($css[$payment_theme])) {
         $css[$payment_theme]['data'] = $path . '/css/commerce/commerce_payment.theme.     css';
         $css[$payment_theme]['group'] = 1;
       }
   }


   // price
   if (module_exists('commerce_price')){
       $price_theme = drupal_get_path('module', 'commerce_price') . '/theme/               commerce_price.theme.css';
       if (isset($css[$price_theme])) {
         $css[$price_theme]['data'] = $path . '/css/commerce/commerce_price.theme.css';
         $css[$price_theme]['group'] = 1;
       }
   }


   // product
   if (module_exists('commerce_product')){
       $product_admin = drupal_get_path('module', 'commerce_product') . '/theme/           commerce_product.admin.css';
       $product_theme = drupal_get_path('module', 'commerce_product') . '/theme/           commerce_product.theme.css';
       if (isset($css[$product_admin])) {
         $css[$product_admin]['data'] = $path . '/css/commerce/commerce_product.admin.     css';
         $css[$product_admin]['group'] = 1;
       }
       if (isset($css[$product_theme])) {
         $css[$product_theme]['data'] = $path . '/css/commerce/commerce_product.theme.     css';
         $css[$product_theme]['group'] = 1;
       }
   }


   // tax
   if (module_exists('commerce_tax')){
       $tax_admin = drupal_get_path('module', 'commerce_tax') . '/theme/commerce_tax.      admin.css';
       $tax_theme = drupal_get_path('module', 'commerce_tax') . '/theme/commerce_tax.      theme.css';
       if (isset($css[$tax_admin])) {
         $css[$tax_admin]['data'] = $path . '/css/commerce/commerce_tax.admin.css';
         $css[$tax_admin]['group'] = 1;
       }
       if (isset($css[$tax_theme])) {
         $css[$tax_theme]['data'] = $path . '/css/commerce/commerce_tax.theme.css';
         $css[$tax_theme]['group'] = 1;
       }
   }
 }