MDL-55272 lib: Improve test course create performance
authorRussell Smith <mr-russ@smith2001.net>
Tue, 19 Jul 2016 00:39:50 +0000 (10:39 +1000)
committerRussell Smith <mr-russ@smith2001.net>
Tue, 16 Aug 2016 02:00:21 +0000 (12:00 +1000)
Use core functions that are faster for test file creation.
To support large requests for hashes, the core hash function
must support large hashes without recursion.  PHP has a default
recursion depth of 100 and long hashes don't support this.

Remove transactions as they create performance problems for larger
courses and doesn't introduce significant benefit for developers.

Performance changes meant the times were much faster, a reasonable
guess was taken on performance of an average machine.

admin/tool/generator/classes/course_backend.php
admin/tool/generator/lang/en/tool_generator.php
lib/classes/event/role_assigned.php
lib/moodlelib.php
lib/tests/moodlelib_test.php

index 0219ebe..e5e7ec4 100644 (file)
@@ -216,19 +216,19 @@ class tool_generator_course_backend extends tool_generator_backend {
 
         $entirestart = microtime(true);
 
-        // Start transaction.
-        $transaction = $DB->start_delegated_transaction();
-
         // Get generator.
         $this->generator = phpunit_util::get_data_generator();
 
         // Make course.
         $this->course = $this->create_course();
-        $this->create_users();
+
         $this->create_assignments();
         $this->create_pages();
         $this->create_small_files();
         $this->create_big_files();
+
+        // Create users as late as possible to reduce regarding in the gradebook.
+        $this->create_users();
         $this->create_forum();
 
         // Log total time.
@@ -238,8 +238,6 @@ class tool_generator_course_backend extends tool_generator_backend {
             echo html_writer::end_tag('ul');
         }
 
-        // Commit transaction and finish.
-        $transaction->allow_commit();
         return $this->course->id;
     }
 
@@ -435,7 +433,7 @@ class tool_generator_course_backend extends tool_generator_backend {
 
             // Generate random binary data (different for each file so it
             // doesn't compress unrealistically).
-            $data = self::get_random_binary($this->limit_filesize(self::$paramsmallfilesize[$this->size]));
+            $data = random_bytes_emulate($this->limit_filesize(self::$paramsmallfilesize[$this->size]));
 
             $fs->create_file_from_string($filerecord, $data);
             $this->dot($i, $count);
@@ -444,33 +442,10 @@ class tool_generator_course_backend extends tool_generator_backend {
         $this->end_log();
     }
 
-    /**
-     * Creates a string of random binary data. The start of the string includes
-     * the current time, in an attempt to avoid large-scale repetition.
-     *
-     * @param int $length Number of bytes
-     * @return Random data
-     */
-    private static function get_random_binary($length) {
-
-        $data = microtime(true);
-        if (strlen($data) > $length) {
-            // Use last digits of data.
-            return substr($data, -$length);
-        }
-        $length -= strlen($data);
-        for ($j = 0; $j < $length; $j++) {
-            $data .= chr(rand(1, 255));
-        }
-        return $data;
-    }
-
     /**
      * Creates a number of resource activities with one big file each.
      */
     private function create_big_files() {
-        global $CFG;
-
         // Work out how many files and how many blocks to use (up to 64KB).
         $count = self::$parambigfilecount[$this->size];
         $filesize = $this->limit_filesize(self::$parambigfilesize[$this->size]);
@@ -499,7 +474,7 @@ class tool_generator_course_backend extends tool_generator_backend {
                 throw new coding_exception('Failed to open temporary file');
             }
             for ($j = 0; $j < $blocks; $j++) {
-                $data = self::get_random_binary($blocksize);
+                $data = random_bytes_emulate($blocksize);
                 fwrite($handle, $data);
                 $this->dot($i * $blocks + $j, $count * $blocks);
             }
index 86247ec..8711269 100644 (file)
@@ -43,10 +43,10 @@ DEVELOPER debugging level.)';
 
 $string['coursesize_0'] = 'XS (~10KB; create in ~1 second)';
 $string['coursesize_1'] = 'S (~10MB; create in ~30 seconds)';
-$string['coursesize_2'] = 'M (~100MB; create in ~5 minutes)';
-$string['coursesize_3'] = 'L (~1GB; create in ~1 hour)';
-$string['coursesize_4'] = 'XL (~10GB; create in ~4 hours)';
-$string['coursesize_5'] = 'XXL (~20GB; create in ~8 hours)';
+$string['coursesize_2'] = 'M (~100MB; create in ~2 minutes)';
+$string['coursesize_3'] = 'L (~1GB; create in ~30 minutes)';
+$string['coursesize_4'] = 'XL (~10GB; create in ~2 hours)';
+$string['coursesize_5'] = 'XXL (~20GB; create in ~4 hours)';
 $string['coursewithoutusers'] = 'The selected course has no users';
 $string['createcourse'] = 'Create course';
 $string['createtestplan'] = 'Create test plan';
index 8396a8d..3eb3cf6 100644 (file)
@@ -105,7 +105,8 @@ class role_assigned extends base {
      */
     protected function get_legacy_logdata() {
         $roles = get_all_roles();
-        $rolenames = role_fix_names($roles, $this->get_context(), ROLENAME_ORIGINAL, true);
+        $neededrole = array($this->objectid => $roles[$this->objectid]);
+        $rolenames = role_fix_names($neededrole, $this->get_context(), ROLENAME_ORIGINAL, true);
         return array($this->courseid, 'role', 'assign', 'admin/roles/assign.php?contextid='.$this->contextid.'&roleid='.$this->objectid,
                 $rolenames[$this->objectid], '', $this->userid);
     }
index 411499f..f77b0d2 100644 (file)
@@ -7803,20 +7803,21 @@ function random_bytes_emulate($length) {
         }
     }
     if (function_exists('openssl_random_pseudo_bytes')) {
-        // For PHP 5.3 and later with openssl extension.
+        // If you have the openssl extension enabled.
         $hash = openssl_random_pseudo_bytes($length);
         if ($hash !== false) {
             return $hash;
         }
     }
 
-    // Bad luck, there is no reliable random generator, let's just hash some unique stuff that is hard to guess.
-    $hash = sha1(serialize($CFG) . serialize($_SERVER) . microtime(true) . uniqid('', true), true);
-    // NOTE: the last param in sha1() is true, this means we are getting 20 bytes, not 40 chars as usual.
-    if ($length <= 20) {
-        return substr($hash, 0, $length);
-    }
-    return $hash . random_bytes_emulate($length - 20);
+    // Bad luck, there is no reliable random generator, let's just slowly hash some unique stuff that is hard to guess.
+    $staticdata = serialize($CFG) . serialize($_SERVER);
+    $hash = '';
+    do {
+        $hash .= sha1($staticdata . microtime(true) . uniqid('', true), true);
+    } while (strlen($hash) < $length);
+
+    return substr($hash, 0, $length);
 }
 
 /**
index 34e05bc..353187e 100644 (file)
@@ -3047,6 +3047,9 @@ class core_moodlelib_testcase extends advanced_testcase {
         $result = random_bytes_emulate(666);
         $this->assertSame(666, strlen($result));
 
+        $result = random_bytes_emulate(40);
+        $this->assertSame(40, strlen($result));
+
         $this->assertDebuggingNotCalled();
 
         $result = random_bytes_emulate(0);