From fdeb890b5f5c5b28a4313593ef551c65d7c23b82 Mon Sep 17 00:00:00 2001
From: Dries Buytaert <dries@buytaert.net>
Date: Wed, 23 Sep 2009 15:04:34 +0000
Subject: [PATCH] - Patch #521838 by catch, jrchamp, CorniI, sun | Damien
 Tournoud, drewish, chx, moshe weitzman, yched, Dries:
 drupal_get_schema_versions() took 30% of page execution time on /admin.

---
 includes/install.inc | 40 +++++++++++++++++++++++++---------------
 1 file changed, 25 insertions(+), 15 deletions(-)

diff --git a/includes/install.inc b/includes/install.inc
index e8efe4b07b92..1fb13883bb99 100644
--- a/includes/install.inc
+++ b/includes/install.inc
@@ -92,24 +92,34 @@ function drupal_load_updates() {
  *   Otherwise, FALSE.
  */
 function drupal_get_schema_versions($module) {
-  $updates = array();
-  $functions = get_defined_functions();
-  foreach ($functions['user'] as $function) {
-    if (strpos($function, $module . '_update_') === 0) {
-      $version = substr($function, strlen($module . '_update_'));
-      if (is_numeric($version)) {
-        $updates[] = $version;
+  $updates = &drupal_static(__FUNCTION__, NULL);
+  if (!isset($updates)) {
+    $updates = array();
+    // Prepare regular expression to match all possible defined hook_update_N().
+    $modules = db_query("SELECT name FROM {system} WHERE type = 'module'")
+      ->fetchCol();
+    $regexp = '/^(?P<module>' . implode('|', $modules) . ')_update_(?P<version>\d+)$/';
+    $functions = get_defined_functions();
+    // Narrow this down to functions ending with an integer, since all
+    // hook_update_N() functions end this way, and there are other
+    // possible functions which match '_update_'. We use preg_grep() here
+    // instead of foreaching through all defined functions, since the loop
+    // through all PHP functions can take significant page execution time
+    // and this function is called on every administrative page via
+    // system_requirements().
+    foreach (preg_grep('/_\d+$/', $functions['user']) as $function) {
+      // If this function is a module update function, add it to the list of
+      // module updates.
+      if (preg_match($regexp, $function, $matches)) {
+        $updates[$matches['module']][] = $matches['version'];
       }
     }
+    // Ensure that updates are applied in numerical order.
+    foreach ($updates as &$module_updates) {
+      sort($module_updates, SORT_NUMERIC);
+    }
   }
-  if (count($updates) == 0) {
-    return FALSE;
-  }
-
-  // Make sure updates are run in numeric order, not in definition order.
-  sort($updates, SORT_NUMERIC);
-
-  return $updates;
+  return isset($updates[$module]) ? $updates[$module] : FALSE;
 }
 
 /**
-- 
GitLab