⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 236956 in webkit


Ignore:
Timestamp:
Oct 8, 2018, 7:17:42 PM (8 years ago)
Author:
rniwa@webkit.org
Message:

/api/report takes 15+ minutes submitting some test results
https://bugs.webkit.org/show_bug.cgi?id=190382

Rubber-stamped by Alexey Proskuryakov and unofficially reviewed by Dewei Zhu.

The issue was that recursively_ensure_tests would issue thousands of dependent queries.

Since most reporting of results would be happening after all the tests and test metrics had been created,
simply fetch the list of all tests and test metrics upfront in memory.

This would slow-down the reporting of other test results but in practice doesn't matter (an extra few seconds
of overhead) but for slow reporting, it can significantly reduce the runtime from ~10 minutes to ~10 seconds.

  • public/include/report-processor.php:

(ReportProcessor::process): Call fetch_tests before recursively_ensure_tests.
(ReportProcessor::fetch_tests): Added. This builds up a mapping of tests based on a parent test ID as well as
a mapping of metrics per test based on its name and then its aggregator's name.
(ReportProcessor::recursively_ensure_tests): Added. Use the in-memory maps built in fetch_tests when possible.
(ReportProcessor::aggregator_list_if_exists): Take a reference instead of passing it by value.
(TestRunsGenerator::add_aggregated_metric): Now takes metric ID. The code to add the test metric had been moved
to recursively_ensure_tests.

Location:
trunk/Websites/perf.webkit.org
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Websites/perf.webkit.org/ChangeLog

    r236861 r236956  
     12018-10-08  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        /api/report takes 15+ minutes submitting some test results
     4        https://bugs.webkit.org/show_bug.cgi?id=190382
     5
     6        Rubber-stamped by Alexey Proskuryakov and unofficially reviewed by Dewei Zhu.
     7
     8        The issue was that recursively_ensure_tests would issue thousands of dependent queries.
     9
     10        Since most reporting of results would be happening after all the tests and test metrics had been created,
     11        simply fetch the list of all tests and test metrics upfront in memory.
     12
     13        This would slow-down the reporting of other test results but in practice doesn't matter (an extra few seconds
     14        of overhead) but for slow reporting, it can significantly reduce the runtime from ~10 minutes to ~10 seconds.
     15
     16        * public/include/report-processor.php:
     17        (ReportProcessor::process): Call fetch_tests before recursively_ensure_tests.
     18        (ReportProcessor::fetch_tests): Added. This builds up a mapping of tests based on a parent test ID as well as
     19        a mapping of metrics per test based on its name and then its aggregator's name.
     20        (ReportProcessor::recursively_ensure_tests): Added. Use the in-memory maps built in fetch_tests when possible.
     21        (ReportProcessor::aggregator_list_if_exists): Take a reference instead of passing it by value.
     22        (TestRunsGenerator::add_aggregated_metric): Now takes metric ID. The code to add the test metric had been moved
     23        to recursively_ensure_tests.
     24
    1252018-10-01  Dewei Zhu  <dewei_zhu@apple.com>
    226
  • trunk/Websites/perf.webkit.org/public/include/report-processor.php

    r227283 r236956  
    3939        $this->ensure_aggregators();
    4040
     41        $this->fetch_tests();
    4142        $this->runs = new TestRunsGenerator($this->db, $this->name_to_aggregator_id, $this->report_id);
    4243        $this->recursively_ensure_tests($report['tests']);
     
    187188    }
    188189
     190    private function fetch_tests() {
     191        $test_rows = $this->db->fetch_table('tests');
     192        $tests = array();
     193        $test_by_id = array();
     194        foreach ($test_rows as &$test) {
     195            $test_by_id[$test['test_id']] = &$test;
     196            $test['metrics'] = array();
     197            $parent_id = $test['test_parent'];
     198            if ($parent_id == NULL)
     199                $parent_id = 0;
     200            $parent_array = &array_ensure_item_has_array($tests, $parent_id);
     201            $parent_array[$test['test_name']] = &$test;
     202        }
     203        $this->tests = &$tests;
     204
     205        $metric_rows = $this->db->fetch_table('test_metrics');
     206        foreach ($metric_rows as &$metric) {
     207            $test = &$test_by_id[$metric['metric_test']];
     208            $metrics_by_name = &array_ensure_item_has_array($test['metrics'], $metric['metric_name']);
     209            $metrics_by_name[$metric['metric_aggregator']] = $metric['metric_id'];
     210        }
     211    }
     212
    189213    private function recursively_ensure_tests(&$tests, $parent_id = NULL, $level = 0) {
    190214        foreach ($tests as $test_name => $test) {
    191             $test_id = $this->db->select_or_insert_row('tests', 'test', $parent_id ? array('name' => $test_name, 'parent' => $parent_id) : array('name' => $test_name),
    192                 array('name' => $test_name, 'parent' => $parent_id, 'url' => array_get($test, 'url')));
     215            $test_row = array_get(array_get($this->tests, $parent_id ? $parent_id : 0, array()), $test_name);
     216            if ($test_row)
     217                $test_id = intval($test_row['test_id']);
     218            else {
     219                $test_id = $this->db->select_or_insert_row('tests', 'test', $parent_id ? array('name' => $test_name, 'parent' => $parent_id) : array('name' => $test_name),
     220                    array('name' => $test_name, 'parent' => $parent_id, 'url' => array_get($test, 'url')));
     221            }
    193222            if (!$test_id)
    194223                $this->exit_with_error('FailedToAddTest', array('name' => $test_name, 'parent' => $parent_id));
     
    197226                $this->recursively_ensure_tests($test['tests'], $test_id, $level + 1);
    198227
    199             foreach (array_get($test, 'metrics', array()) as $metric_name => $aggregators_or_config_types) {
     228            foreach (array_get($test, 'metrics', array()) as $metric_name => &$aggregators_or_config_types) {
    200229                $aggregators = $this->aggregator_list_if_exists($aggregators_or_config_types);
    201230                if ($aggregators) {
    202                     foreach ($aggregators as $aggregator_name)
    203                         $this->runs->add_aggregated_metric($parent_id, $test_id, $test_name, $metric_name, $aggregator_name, $level);
     231                    foreach ($aggregators as $aggregator_name) {
     232                        $aggregator_id = array_get($this->name_to_aggregator_id, $aggregator_name, NULL);
     233                        if ($aggregator_id == NULL)
     234                            $this->exit_with_error('AggregatorNotFound', array('name' => $aggregator_name));
     235
     236                        $metrics = $test_row ? array_get($test_row['metrics'], $metric_name) : NULL;
     237                        $metric_id = $metrics ? $metrics[$aggregator_id] : NULL;
     238                        if (!$metric_id) {
     239                            $metric_id = $this->db->select_or_insert_row('test_metrics', 'metric', array('name' => $metric_name,
     240                                'test' => $test_id, 'aggregator' => $this->name_to_aggregator_id[$aggregator_name]));
     241                        }
     242                        if (!$metric_id)
     243                            $this->exit_with_error('FailedToAddAggregatedMetric', array('name' => $metric_name, 'test' => $test_id, 'aggregator' => $aggregator_name));
     244
     245                        $this->runs->add_aggregated_metric($parent_id, $test_id, $test_name, $metric_id, $metric_name, $aggregator_name, $level);
     246                    }
    204247                } else {
    205                     $metric_id = $this->db->select_or_insert_row('test_metrics', 'metric', array('name' => $metric_name, 'test' => $test_id));
     248                    $metrics = $test_row ? array_get($test_row['metrics'], $metric_name) : NULL;
     249                    $metric_id = $metrics ? $metrics[''] : NULL;
     250                    if (!$metric_id)
     251                        $metric_id = $this->db->select_or_insert_row('test_metrics', 'metric', array('name' => $metric_name, 'test' => $test_id));
    206252                    if (!$metric_id)
    207253                        $this->exit_with_error('FailedToAddMetric', array('name' => $metric_name, 'test' => $test_id));
    208254
    209                     foreach ($aggregators_or_config_types as $config_type => $values) {
     255                    foreach ($aggregators_or_config_types as $config_type => &$values) {
    210256                        // Some tests submit groups of iterations; e.g. [[1, 2, 3, 4], [5, 6, 7, 8]]
    211257                        // Convert other tests to this format to simplify the computation later.
     
    222268    }
    223269
    224     private function aggregator_list_if_exists($aggregators_or_config_types) {
     270    private function aggregator_list_if_exists(&$aggregators_or_config_types) {
    225271        if (array_key_exists(0, $aggregators_or_config_types))
    226272            return $aggregators_or_config_types;
     
    255301    }
    256302
    257     function add_aggregated_metric($parent_id, $test_id, $test_name, $metric_name, $aggregator_name, $level) {
    258         array_key_exists($aggregator_name, $this->name_to_aggregator_id)
    259             or $this->exit_with_error('AggregatorNotFound', array('name' => $aggregator_name));
    260 
    261         $metric_id = $this->db->select_or_insert_row('test_metrics', 'metric', array('name' => $metric_name,
    262             'test' => $test_id, 'aggregator' => $this->name_to_aggregator_id[$aggregator_name]));
    263         if (!$metric_id)
    264             $this->exit_with_error('FailedToAddAggregatedMetric', array('name' => $metric_name, 'test' => $test_id, 'aggregator' => $aggregator_name));
    265 
     303    function add_aggregated_metric($parent_id, $test_id, $test_name, $metric_id, $metric_name, $aggregator_name, $level) {
    266304        array_push($this->metrics_to_aggregate, array(
    267305            'test_id' => $test_id,
Note: See TracChangeset for help on using the changeset viewer.