Commit 47c23a11 authored by unknown's avatar unknown

Speed up mysql-test-run.pl.

Problem was the parsing of test suite files for various tags and options.
This was done inefficiently, and include files were re-parsed for every
place they were included. This caused a delay of 20 seconds or so before
the first test started to run.

By parsing more efficiently and re-using first parse for subsequent
inclusion of the same file, time spent parsing is reduced to less than
1 second, and start appears instantaneous.

(With this patch, full ./mtr runs in 3 minutes on my laptop (release
build.)

mysql-test/suite/innodb_plugin/t/innodb_bug52663.test:
  Test is fairly slow, so try to avoid getting stuck with it at the end
  while other workers are idle.
parent db9291fa
...@@ -890,7 +890,8 @@ sub collect_one_test_case { ...@@ -890,7 +890,8 @@ sub collect_one_test_case {
if ( -f "$testdir/$tname.slave-mi"); if ( -f "$testdir/$tname.slave-mi");
my @source_files = tags_from_test_file($tinfo,"$testdir/${tname}.test"); my ($master_opts, $slave_opts)=
tags_from_test_file($tinfo, "$testdir/${tname}.test", $suitedir);
# Get default storage engine from suite.opt file # Get default storage engine from suite.opt file
...@@ -1043,16 +1044,8 @@ sub collect_one_test_case { ...@@ -1043,16 +1044,8 @@ sub collect_one_test_case {
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# Append mysqld extra options to master and slave, as appropriate # Append mysqld extra options to master and slave, as appropriate
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
for (@source_files) { push @{$tinfo->{'master_opt'}}, @$master_opts, @::opt_extra_mysqld_opt;
s/\.\w+$//; push @{$tinfo->{'slave_opt'}}, @$slave_opts, @::opt_extra_mysqld_opt;
push @{$tinfo->{master_opt}}, opts_from_file("$_.opt");
push @{$tinfo->{slave_opt}}, opts_from_file("$_.opt");
push @{$tinfo->{master_opt}}, opts_from_file("$_-master.opt");
push @{$tinfo->{slave_opt}}, opts_from_file("$_-slave.opt");
}
push(@{$tinfo->{'master_opt'}}, @::opt_extra_mysqld_opt);
push(@{$tinfo->{'slave_opt'}}, @::opt_extra_mysqld_opt);
process_opts($tinfo, 'master_opt'); process_opts($tinfo, 'master_opt');
process_opts($tinfo, 'slave_opt'); process_opts($tinfo, 'slave_opt');
...@@ -1061,73 +1054,113 @@ sub collect_one_test_case { ...@@ -1061,73 +1054,113 @@ sub collect_one_test_case {
} }
# List of tags in the .test files that if found should set my $tags_map= {'big_test' => ['big_test', 1],
# the specified value in "tinfo" 'have_debug' => ['need_debug', 1],
my @tags= 'have_ndb' => ['ndb_test', 1],
( 'have_multi_ndb' => ['ndb_test', 1],
["include/big_test.inc", "big_test", 1], 'master-slave' => ['rpl_test', 1],
["include/have_debug.inc", "need_debug", 1], 'ndb_master-slave' => ['rpl_test', 1, 'ndb_test', 1],
["include/have_ndb.inc", "ndb_test", 1], 'not_embedded' => ['not_embedded', 1],
["include/have_multi_ndb.inc", "ndb_test", 1], 'not_valgrind' => ['not_valgrind', 1],
["include/master-slave.inc", "rpl_test", 1], 'have_example_plugin' => ['example_plugin_test', 1],
["include/ndb_master-slave.inc", "rpl_test", 1], 'have_oqgraph_engine' => ['oqgraph_test', 1],
["include/ndb_master-slave.inc", "ndb_test", 1], 'have_ssl' => ['need_ssl', 1],
["include/not_embedded.inc", "not_embedded", 1], 'long_test' => ['long_test', 1],
["include/not_valgrind.inc", "not_valgrind", 1], };
["include/have_example_plugin.inc", "example_plugin_test", 1], my $tags_regex_string= join('|', keys %$tags_map);
["include/have_ssl.inc", "need_ssl", 1], my $tags_regex= qr:include/($tags_regex_string)\.inc:o;
["include/long_test.inc", "long_test", 1],
); my $file_to_tags= { };
my $file_to_master_opts= { };
my $file_to_slave_opts= { };
sub tags_from_test_file {
my $tinfo= shift; # Get various tags from a file, recursively scanning also included files.
my $file= shift; # And get options from .opt file, also recursively for included files.
#mtr_verbose("$file"); # Return a list of [TAG_TO_SET, VALUE_TO_SET_TO] of found tags.
my $F= IO::File->new($file) or mtr_error("can't open file \"$file\": $!"); # Also returns lists of options for master and slave found in .opt files.
my @all_files=($file); # Each include file is scanned only once, and subsequent calls just look up the
# cached result.
while ( my $line= <$F> ) # We need to be a bit careful about speed here; previous version of this code
{ # took forever to scan the full test suite.
sub get_tags_from_file {
# Skip line if it start's with # my ($file, $suitedir)= @_;
next if ( $line =~ /^#/ );
return ($file_to_tags->{$file}, $file_to_master_opts->{$file},
# Match this line against tag in "tags" array $file_to_slave_opts->{$file})
foreach my $tag (@tags) if exists($file_to_tags->{$file});
{
if ( index($line, $tag->[0]) >= 0 ) my $F= IO::File->new($file)
{ or mtr_error("can't open file \"$file\": $!");
# Tag matched, assign value to "tinfo"
$tinfo->{"$tag->[1]"}= $tag->[2]; my $tags= [];
my $master_opts= [];
my $slave_opts= [];
while (my $line= <$F>)
{
# Ignore comments.
next if $line =~ /^\#/;
# Add any tag we find.
if ($line =~ /$tags_regex/o)
{
my $to_set= $tags_map->{$1};
for (my $i= 0; $i < @$to_set; $i+= 2)
{
push @$tags, [$to_set->[$i], $to_set->[$i+1]];
}
}
# Check for a sourced include file.
if ($line =~ /^(--)?[[:space:]]*source[[:space:]]+([^;[:space:]]+)/)
{
my $include= $2;
# Sourced file may exist relative to test file, or in global location.
# Note that for the purpose of tag collection we ignore
# non-existing files, and let mysqltest handle the error
# (e.g. mysqltest.test needs this)
for my $sourced_file (dirname($file) . '/' . $include,
$suitedir . '/' . $include,
$::glob_mysql_test_dir . '/' . $include)
{
if (-e $sourced_file)
{
my ($sub_tags, $sub_master_opts, $sub_slave_opts)=
get_tags_from_file($sourced_file, $suitedir);
push @$tags, @$sub_tags;
push @$master_opts, @$sub_master_opts;
push @$slave_opts, @$sub_slave_opts;
last;
}
}
} }
} }
# If test sources another file, open it as well # Add options from main file _after_ those of any includes; this allows a
if ( $line =~ /^\-\-([[:space:]]*)source(.*)$/ or # test file to override options set by includes (eg. rpl.rpl_ddl uses this
$line =~ /^([[:space:]]*)source(.*);$/ ) # to enable innodb, then disable innodb in the slave.
{ my $file_no_ext= $file;
my $value= $2; $file_no_ext =~ s/\.\w+$//;
$value =~ s/^\s+//; # Remove leading space my @common_opts= opts_from_file("$file_no_ext.opt");
$value =~ s/[[:space:]]+$//; # Remove ending space push @$master_opts, @common_opts, opts_from_file("$file_no_ext-master.opt");
push @$slave_opts, @common_opts, opts_from_file("$file_no_ext-slave.opt");
# Sourced file may exist relative to test or # Save results so we can reuse without parsing if seen again.
# in global location $file_to_tags->{$file}= $tags;
foreach my $sourced_file (dirname($file). "/$value", $file_to_master_opts->{$file}= $master_opts;
"$::glob_mysql_test_dir/$value") $file_to_slave_opts->{$file}= $slave_opts;
{ return ($tags, $master_opts, $slave_opts);
if ( -f $sourced_file ) }
sub tags_from_test_file {
my ($tinfo, $file, $suitedir)= @_;
my ($tags, $master_opts, $slave_opts)= get_tags_from_file($file, $suitedir);
for (@$tags)
{ {
# Only source the file if it exists, we may get $tinfo->{$_->[0]}= $_->[1];
# false positives in the regexes above if someone
# writes "source nnnn;" in a test case(such as mysqltest.test)
unshift @all_files, tags_from_test_file($tinfo, $sourced_file);
last;
}
}
}
} }
@all_files; return ($master_opts, $slave_opts);
} }
sub unspace { sub unspace {
......
--source include/have_innodb_plugin.inc --source include/have_innodb_plugin.inc
--source include/long_test.inc
set session transaction isolation level read committed; set session transaction isolation level read committed;
create table innodb_bug52663 (what varchar(5), id integer, count integer, primary key create table innodb_bug52663 (what varchar(5), id integer, count integer, primary key
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment