Change the database layout so that the breakdown table now references

tests relationally in a new awfy_suite_test table. This reduces the
breakdown table size about 10% and greatly improves the performance of
querying test names. This update requires running db_upgrade.py and
using the new UDPATE.php and internals.php changes.

In addition, this patch skips the condensing step when we already have a
condense file for a previous month. This improves the update.py running
time by about 50%.
This commit is contained in:
David Anderson 2013-10-18 01:13:39 +00:00 коммит произвёл AreWeFastYet
Родитель 3f9f931fa4
Коммит f3647984f8
7 изменённых файлов: 121 добавлений и 22 удалений

Просмотреть файл

@ -86,6 +86,14 @@ CREATE TABLE `awfy_suite` (
UNIQUE KEY `name_UNIQUE` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=9 ;
CREATE TABLE IF NOT EXISTS `awfy_suite_test` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`suite_id` int(11) NOT NULL,
`name` varchar(128) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `suite_id` (`suite_id`,`name`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
--
-- Dumping data for table `awfy_suite`
--
@ -156,14 +164,13 @@ CREATE TABLE `awfy_breakdown` (
`run_id` int(11) DEFAULT NULL,
`suite_id` int(11) DEFAULT NULL,
`mode_id` int(11) DEFAULT NULL,
`test` varchar(45) DEFAULT NULL,
`score` varchar(45) DEFAULT NULL,
`test_id` int(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `run_id` (`run_id`),
KEY `suite_id` (`suite_id`),
KEY `mode_id` (`mode_id`),
KEY `suite_id_2` (`suite_id`,`test`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=7636046 ;
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
-- --------------------------------------------------------
@ -178,7 +185,7 @@ CREATE TABLE `awfy_build` (
`cset` varchar(256) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index2` (`run_id`,`mode_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=136734 ;
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
-- --------------------------------------------------------
@ -195,7 +202,7 @@ CREATE TABLE `awfy_machine` (
`last_checked` int(10) unsigned NOT NULL,
`contact` mediumtext NOT NULL
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=16 ;
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
-- --------------------------------------------------------
@ -212,7 +219,7 @@ CREATE TABLE `awfy_score` (
PRIMARY KEY (`id`),
KEY `run_id` (`run_id`),
KEY `mode_id` (`mode_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=480043 ;
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
-- --------------------------------------------------------
@ -228,5 +235,5 @@ CREATE TABLE `fast_run` (
`status` int(11) NOT NULL,
`error` mediumtext NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=33848 ;
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

Просмотреть файл

@ -9,10 +9,20 @@ import sys
import awfy
import json
from profiler import Profiler
from datetime import datetime
SecondsPerDay = 60 * 60 * 24
MaxRecentRuns = 30
def should_export(name, when):
path = os.path.join(awfy.path, name)
if not os.path.exists(path):
return True
now = datetime.now()
if now.year == when[0] and now.month == when[1]:
return True
return False
def export(name, j):
path = os.path.join(awfy.path, name)
if os.path.exists(path):
@ -208,6 +218,11 @@ def condense(cx, suite, prefix, name):
for when, graph in graphs:
new_name = prefix + 'condensed-' + name + '-' + str(when[0]) + '-' + str(when[1])
# Don't condense if it already exists...
if not should_export(new_name + '.json', when):
continue
sys.stdout.write('Condensing ' + new_name + '... ')
sys.stdout.flush()
with Profiler() as p:
@ -233,13 +248,13 @@ def condense_suite(cx, machine, suite):
# the combine graph back to our caller.
suite_aggregate = condense(cx, suite, '', name)
for test in suite.tests:
test_name = suite.name + '-' + test + '-' + str(machine.id)
test_aggregate = condense(cx, suite, 'bk-', test_name)
for test_id, test_name in suite.tests:
test_path = suite.name + '-' + test_name + '-' + str(machine.id)
test_aggregate = condense(cx, suite, 'bk-', test_path)
j = { 'version': awfy.version,
'graph': test_aggregate
}
export('bk-aggregate-' + test_name + '.json', j)
export('bk-aggregate-' + test_path + '.json', j)
return suite_aggregate

Просмотреть файл

@ -17,12 +17,9 @@ class Benchmark(object):
# Get a list of individual tests
self.tests = []
c = awfy.db.cursor()
c.execute("SELECT test FROM awfy_breakdown \
WHERE suite_id = %s \
GROUP BY test",
[suite_id])
c.execute("select id, name from awfy_suite_test where suite_id = %s", (suite_id,))
for row in c.fetchall():
self.tests.append(row[0])
self.tests.append((row[0], row[1]))
def export(self):
return { "id": self.id,

66
server/db_upgrade.py Normal file
Просмотреть файл

@ -0,0 +1,66 @@
# vim: set sts=4 ts=8 sw=4 tw=99 et:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import awfy
awfy.Startup()
c = awfy.db.cursor()
c.execute("show tables;")
tables = set()
for row in c.fetchall():
tables.add(row[0])
if not 'awfy_suite_test' in tables:
c.execute("""
create table if not exists `awfy_suite_test` (
`id` int(10) unsigned not null auto_increment,
`suite_id` int(11) not null,
`name` varchar(128) not null,
primary key(`id`),
unique key `suite_id` (`suite_id`, `name`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
""")
awfy_breakdown_columns = set()
c.execute("show columns from awfy_breakdown")
for row in c.fetchall():
awfy_breakdown_columns.add(row[0])
if 'test_id' not in awfy_breakdown_columns:
print('Creating new column on awfy_breakdown_columns...')
c.execute("alter table `awfy_breakdown` add `test_id` int unsigned not null")
if 'test' in awfy_breakdown_columns:
print('Finding tests...')
suite_map = {}
c.execute("select distinct suite_id, test from awfy_breakdown where test is not null")
for row in c.fetchall():
suite_id = row[0]
test_name = row[1]
if suite_id not in suite_map:
suite_map[suite_id] = {}
test_map = suite_map[suite_id]
c.execute("select id from awfy_suite_test where suite_id = %s and name = %s",
(suite_id, test_name))
result = c.fetchone()
if not result:
c.execute("insert into awfy_suite_test (suite_id, name) values (%s, %s)",
(suite_id, test_name))
test_id = c.lastrowid
else:
test_id = result[0]
test_map[test_name] = test_id
for suite_id in suite_map:
test_map = suite_map[suite_id]
for test_name in test_map:
test_id = test_map[test_name]
print('Updating columns for suite_id {0} test {1} to test_id {2}'.format(suite_id, test_name, test_id))
c.execute("update awfy_breakdown set test_id = %s where suite_id = %s and test = %s",
(test_id, suite_id, test_name))
print('Dropping old column...')
c.execute("alter table `awfy_breakdown` drop `test`")

Просмотреть файл

@ -51,7 +51,7 @@ def fetch_test_scores(machine_id, suite_id, name, earliest_run_id):
JOIN fast_run r ON s.run_id = r.id \
JOIN awfy_build b ON (s.run_id = b.run_id AND s.mode_id = b.mode_id) \
WHERE s.suite_id = %s \
AND s.test = %s \
AND s.test_id = %s \
AND r.status = 1 \
AND r.machine = %s \
AND r.id > %s \
@ -254,11 +254,11 @@ def update(cx, machine, suite):
if not new_rows:
return
for test in suite.tests:
for test_id, test_name in suite.tests:
def fetch_test(earliest_run_id):
return fetch_test_scores(machine.id, suite.id, test, earliest_run_id)
return fetch_test_scores(machine.id, suite.id, test_id, earliest_run_id)
prefix = 'bk-raw-' + suite.name + '-' + test + '-' + str(machine.id)
prefix = 'bk-raw-' + suite.name + '-' + test_name + '-' + str(machine.id)
perform_update(cx, suite, prefix, fetch_test)
def export_master(cx):

Просмотреть файл

@ -49,10 +49,11 @@ if (isset($_GET['run']) && $_GET['run'] == 'yes') {
($run, $suite_id, $mode_id, $time)")
or die("ERROR: " . mysql_error());
} else {
$test_id = find_or_add_test($suite_id, $name);
mysql_query("INSERT INTO awfy_breakdown
(run_id, suite_id, mode_id, test, score)
(run_id, suite_id, mode_id, score, test_id)
VALUES
($run, $suite_id, $mode_id, '$name', $time)")
($run, $suite_id, $mode_id, $time, $test_id)")
or die("ERROR: " . mysql_error());
}
}

Просмотреть файл

@ -57,6 +57,19 @@ function find_suite($suite)
return intval($row[0]);
}
function find_or_add_test($suite_id, $name)
{
$query = "select id from awfy_suite_test where suite_id = $suite_id and name = '$name'";
$results = mysql_query($query);
if (!$results || mysql_num_rows($results) < 1) {
$query = "insert into awfy_suite_test (suite_id, name) values($suite_id, $name)";
mysql_query($query);
return mysql_insert_id();
}
$row = mysql_fetch_array($results);
return intval($row[0]);
}
function awfy_query($query)
{
$result = mysql_query($query) or die(mysql_error());