Skip to content

Commit 29fb2ec

Browse files
sunshinecogitster
authored andcommitted
chainlint.pl: validate test scripts in parallel
Although chainlint.pl has undergone a good deal of optimization during its development -- increasing in speed significantly -- parsing and validating 1050+ scripts and 16500+ tests via Perl is not exactly instantaneous. However, perceived performance can be improved by taking advantage of the fact that there is no interdependence between test scripts or test definitions, thus parsing and validating can be done in parallel. The number of available cores is determined automatically but can be overridden via the --jobs option. Signed-off-by: Eric Sunshine <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d99ebd6 commit 29fb2ec

File tree

1 file changed

+49
-1
lines changed

1 file changed

+49
-1
lines changed

t/chainlint.pl

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515

1616
use warnings;
1717
use strict;
18+
use Config;
1819
use File::Glob;
1920
use Getopt::Long;
2021

22+
my $jobs = -1;
2123
my $show_stats;
2224
my $emit_all;
2325

@@ -569,6 +571,16 @@ package main;
569571
$interval = sub { return Time::HiRes::tv_interval(shift); };
570572
}
571573

574+
sub ncores {
575+
# Windows
576+
return $ENV{NUMBER_OF_PROCESSORS} if exists($ENV{NUMBER_OF_PROCESSORS});
577+
# Linux / MSYS2 / Cygwin / WSL
578+
do { local @ARGV='/proc/cpuinfo'; return scalar(grep(/^processor\s*:/, <>)); } if -r '/proc/cpuinfo';
579+
# macOS & BSD
580+
return qx/sysctl -n hw.ncpu/ if $^O =~ /(?:^darwin$|bsd)/;
581+
return 1;
582+
}
583+
572584
sub show_stats {
573585
my ($start_time, $stats) = @_;
574586
my $walltime = $interval->($start_time);
@@ -621,7 +633,9 @@ sub exit_code {
621633
Getopt::Long::Configure(qw{bundling});
622634
GetOptions(
623635
"emit-all!" => \$emit_all,
636+
"jobs|j=i" => \$jobs,
624637
"stats|show-stats!" => \$show_stats) or die("option error\n");
638+
$jobs = ncores() if $jobs < 1;
625639

626640
my $start_time = $getnow->();
627641
my @stats;
@@ -633,6 +647,40 @@ sub exit_code {
633647
exit;
634648
}
635649

636-
push(@stats, check_script(1, sub { shift(@scripts); }, sub { print(@_); }));
650+
unless ($Config{useithreads} && eval {
651+
require threads; threads->import();
652+
require Thread::Queue; Thread::Queue->import();
653+
1;
654+
}) {
655+
push(@stats, check_script(1, sub { shift(@scripts); }, sub { print(@_); }));
656+
show_stats($start_time, \@stats) if $show_stats;
657+
exit(exit_code(\@stats));
658+
}
659+
660+
my $script_queue = Thread::Queue->new();
661+
my $output_queue = Thread::Queue->new();
662+
663+
sub next_script { return $script_queue->dequeue(); }
664+
sub emit { $output_queue->enqueue(@_); }
665+
666+
sub monitor {
667+
while (my $s = $output_queue->dequeue()) {
668+
print($s);
669+
}
670+
}
671+
672+
my $mon = threads->create({'context' => 'void'}, \&monitor);
673+
threads->create({'context' => 'list'}, \&check_script, $_, \&next_script, \&emit) for 1..$jobs;
674+
675+
$script_queue->enqueue(@scripts);
676+
$script_queue->end();
677+
678+
for (threads->list()) {
679+
push(@stats, $_->join()) unless $_ == $mon;
680+
}
681+
682+
$output_queue->end();
683+
$mon->join();
684+
637685
show_stats($start_time, \@stats) if $show_stats;
638686
exit(exit_code(\@stats));

0 commit comments

Comments
 (0)