diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index cfc0497..850ab9a 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -524,6 +524,7 @@ function install_begin_request($class_loader, &$install_state) {
  *   HTML output from the last completed task.
  */
 function install_run_tasks(&$install_state) {
+  $stopwatch = new \Symfony\Component\Stopwatch\Stopwatch();
   do {
     // Obtain a list of tasks to perform. The list of tasks itself can be
     // dynamic (e.g., some might be defined by the installation profile,
@@ -536,6 +537,7 @@ function install_run_tasks(&$install_state) {
     $task_name = key($tasks_to_perform);
     $task = array_shift($tasks_to_perform);
     $install_state['active_task'] = $task_name;
+    $stopwatch->start($task_name);
     $original_parameters = $install_state['parameters'];
     $output = install_run_task($task, $install_state);
     // Ensure the maintenance theme is initialized. If the install task has
@@ -560,6 +562,19 @@ function install_run_tasks(&$install_state) {
     // the URL parameters have changed, or an end to the page request was
     // specifically called for.
     $finished = empty($tasks_to_perform) || ($install_state['interactive'] && (isset($output) || $install_state['parameters_changed'] || $install_state['stop_page_request']));
+    $profile = $stopwatch->stop($task_name);
+    $install_log = \Drupal::state()->get('install_log', []);
+    if (isset($install_log[$task_name])) {
+      $install_log[$task_name]['time'] += $profile->getDuration();
+      $install_log[$task_name]['memory'] += $profile->getMemory();
+      $install_log[$task_name]['count']++;
+    }
+    else {
+      $install_log[$task_name]['time'] = $profile->getDuration();
+      $install_log[$task_name]['memory'] = $profile->getMemory();
+      $install_log[$task_name]['count'] = 1;
+    }
+    \Drupal::state()->set('install_log', $install_log);
   } while (!$finished);
   return $output;
 }
