Download & Extend

skinr_process_info_files() calls the slow _system_theme_data()

Project:Skinr
Version:6.x-1.x-dev
Component:Code
Category:bug report
Priority:normal
Assigned:Unassigned
Status:needs review

Issue Summary

_system_theme_data() reads theme files from the disk and executes drupal_alter.
On a system with many modules and/or themes this adds a performance hit.

Replacing _system_theme_data() with a DB read of the system table (as done in common.inc's list_themes()) can greatly improve performance.

$result = db_query("SELECT * FROM {system} WHERE type = '%s'", 'theme');
while ($theme = db_fetch_object($result)) {
  if (file_exists($theme->filename)) {
    $theme->info = unserialize($theme->info);
    $themes[] = $theme;
  }
}

is around 40-50x faster than
  _system_theme_data()

Patch follows.

Comments

#1

AttachmentSizeStatusTest resultOperations
skinr-system-theme-data-1129746-1.patch1.53 KBTest request sentNoneView details

#2

Refer #1

I like it: +1 rating

Good lateral thinking setvik

I had several issues with the private _system_theme_data() method
used in skinr 6.x-1.x-dev

#4

I have updated your patch in #1:

I was getting PHP E-Notices: ==> Notice: Trying to get property of non-object in system_find_base_themes()

New code (below):

<?php
/**
* Helper function to load theme data
* Code borrowed from list_themes().
*
* If the database is active then it will be retrieved from the database.
* Otherwise it will retrieve a new list.
*
* @return
*   An array of the currently available themes.
*/
function _skinr_get_theme_data() {
  static
$themes = array();

  if (empty(
$themes)) {
   
$themes = array();
   
// Extract from the database only when it is available.
    // Also check that the site is not in the middle of an install or update.
   
if (db_is_active() && !defined('MAINTENANCE_MODE')) {
     
$result = db_query("SELECT * FROM {system} WHERE type = '%s'", 'theme');
      while (
$theme = db_fetch_object($result)) {
        if (
file_exists($theme->filename)) {
         
$theme->info = unserialize($theme->info);
         
$themes[] = $theme;
        }
      }
    }
    else {
     
// Scan the installation when the database should not be read.
     
$themes = _system_theme_data();
    }

    foreach (
$themes as $theme) {
      foreach (
$theme->info['stylesheets'] as $media => $stylesheets) {
        foreach (
$stylesheets as $stylesheet => $path) {
         
$theme->stylesheets[$media][$stylesheet] = $path;
        }
      }
      foreach (
$theme->info['scripts'] as $script => $path) {
        if (
file_exists($path)) {
         
$theme->scripts[$script] = $path;
        }
      }
      if (isset(
$theme->info['engine'])) {
       
$theme->engine = $theme->info['engine'];
      }
      if (isset(
$theme->info['base theme'])) {
       
$theme->base_theme = $theme->info['base theme'];
      }
     
// Status is normally retrieved from the database. Add zero values when
      // read from the installation directory to prevent notices.
     
if (!isset($theme->status)) {
       
$theme->status = 0;
      }
     
$themes[$theme->name] = $theme;
    }

  }
  return
$themes;
}
?>

I no longer see PHP 5.3.x 'E-Notice' reports via Pressflow 6.22.

nobody click here