parallel: Fixed bug in optimized finding (grand)*parent shell.

This commit is contained in:
Ole Tange 2019-06-26 13:46:29 +02:00
parent 7aa0394278
commit a24bef3d03
5 changed files with 56 additions and 20 deletions

View file

@ -222,9 +222,9 @@ Quote of the month:
New in this release: New in this release:
* {= uq; =} will cause the replacement string to be unquoted. Example: parallel echo '{=uq;=}.jpg' ::: '*' * {= uq; =} causes the replacement string to be unquoted. Example: parallel echo '{=uq;=}.jpg' ::: '*'
* Speedup of startup by 40%: Find the parent shell differerently on GNU/Linux, cache information about the CPU and which setpgrp method to make GNU Parallel start 40% faster. * Speedup of startup by 40%: Find the parent shell differerently on GNU/Linux, cache information about the CPU and which setpgrp method to use to make GNU Parallel start 40% faster.
https://techieroop.com/how-to-run-multiple-bash-scripts-in-parallel/ https://techieroop.com/how-to-run-multiple-bash-scripts-in-parallel/

View file

@ -19,8 +19,7 @@
# open3 used in Job::start # open3 used in Job::start
use IPC::Open3; use IPC::Open3;
# &WNOHANG used in reaper use POSIX;
use POSIX qw(:sys_wait_h setsid ceil :errno_h);
# gensym used in Job::start # gensym used in Job::start
use Symbol qw(gensym); use Symbol qw(gensym);
# tempfile used in Job::start # tempfile used in Job::start
@ -5080,7 +5079,7 @@ sub tmpname($) {
sub tmpfifo() { sub tmpfifo() {
# Find an unused name and mkfifo on it # Find an unused name and mkfifo on it
use POSIX qw(mkfifo); # use POSIX qw(mkfifo);
my $tmpfifo = tmpname("fif"); my $tmpfifo = tmpname("fif");
mkfifo($tmpfifo,0600); mkfifo($tmpfifo,0600);
return $tmpfifo; return $tmpfifo;
@ -5426,7 +5425,7 @@ sub which(@) {
"-sh (sh)" => ["sh"], "-sh (sh)" => ["sh"],
# csh and tcsh disguise themselves as -sh/-csh # csh and tcsh disguise themselves as -sh/-csh
# E.g.: ssh -tt csh@lo 'ps aux;true' |egrep ^csh # E.g.: ssh -tt csh@lo 'ps aux;true' |egrep ^csh
# but sh also disguise itself as -sh # but sh also disguises itself as -sh
# (TODO When does that happen?) # (TODO When does that happen?)
"-sh" => ["sh"], "-sh" => ["sh"],
"-csh" => ["tcsh", "csh"], "-csh" => ["tcsh", "csh"],
@ -5446,16 +5445,35 @@ sub which(@) {
# Optimized for GNU/Linux # Optimized for GNU/Linux
my $testpid = $pid; my $testpid = $pid;
my $shellpath; my $shellpath;
my $shellline;
while($testpid) { while($testpid) {
if($shellpath = readlink "/proc/$testpid/exe") { if(open(my $fd, "<", "/proc/$testpid/cmdline")) {
if($shellpath =~ m:/$shell$:o) { local $/="\0";
::debug("init", "proc which ".$shellpath." => "); chomp($shellline = <$fd>);
if($shellline =~ /$regexp/o) {
my $shellname = $4 || $8;
my $dash = $3 || $7;
if($shellname eq "sh" and $dash) {
# -sh => csh or sh
if($shellpath = readlink "/proc/$testpid/exe") {
::debug("init","procpath $shellpath\n");
if($shellpath =~ m:/$shell$:o) {
::debug("init", "proc which ".$shellpath." => ");
return $shellpath;
}
}
}
::debug("init", "which ".$shellname." => ");
$shellpath = (which($shellname,@{$fakename{$shellname}}))[0];
::debug("init", "shell path $shellpath\n");
return $shellpath; return $shellpath;
} }
} }
# Get parent pid
if(open(my $fd, "<", "/proc/$testpid/stat")) { if(open(my $fd, "<", "/proc/$testpid/stat")) {
my $line = <$fd>; my $line = <$fd>;
close $fd; close $fd;
# Parent pid is field 4
$testpid = (split /\s+/, $line)[3]; $testpid = (split /\s+/, $line)[3];
} else { } else {
# Something is wrong: fall back to old method # Something is wrong: fall back to old method
@ -6995,8 +7013,9 @@ sub socket_core_thread() {
::hostname() . "/cpuspec"; ::hostname() . "/cpuspec";
if(-e $cached_cpuspec and -M $cached_cpuspec < 1) { if(-e $cached_cpuspec and -M $cached_cpuspec < 1) {
# Reading cached copy instead of /proc/cpuinfo is 17 ms faster # Reading cached copy instead of /proc/cpuinfo is 17 ms faster
local $/ = "\n";
if(open(my $in_fh, "<", $cached_cpuspec)) { if(open(my $in_fh, "<", $cached_cpuspec)) {
::debug("init","Read $cached_cpuspec"); ::debug("init","Read $cached_cpuspec\n");
$cpu->{'sockets'} = int(<$in_fh>); $cpu->{'sockets'} = int(<$in_fh>);
$cpu->{'cores'} = int(<$in_fh>); $cpu->{'cores'} = int(<$in_fh>);
$cpu->{'threads'} = int(<$in_fh>); $cpu->{'threads'} = int(<$in_fh>);
@ -8144,12 +8163,12 @@ sub remove_rec_sep($) {
sub non_blocking_write($) { sub non_blocking_write($) {
my $self = shift; my $self = shift;
my $something_written = 0; my $something_written = 0;
use POSIX qw(:errno_h); # use POSIX qw(:errno_h);
my $in = $self->fh(0,"w"); my $in = $self->fh(0,"w");
my $rv = syswrite($in, my $rv = syswrite($in,
substr($self->{'block'},$self->{'block_pos'})); substr($self->{'block'},$self->{'block_pos'}));
if (!defined($rv) && $! == EAGAIN) { if (!defined($rv) && $! == EAGAIN()) {
# would block - but would have written # would block - but would have written
$something_written = 0; $something_written = 0;
# avoid triggering auto expanding block # avoid triggering auto expanding block
@ -9224,6 +9243,7 @@ sub start($) {
my $setgprp_cache = $Global::cache_dir . "/tmp/sshlogin/" . my $setgprp_cache = $Global::cache_dir . "/tmp/sshlogin/" .
::hostname() . "/setpgrp_func"; ::hostname() . "/setpgrp_func";
if(-e $setgprp_cache) { if(-e $setgprp_cache) {
local $/ = undef;
open(my $fh, "<", $setgprp_cache) || die; open(my $fh, "<", $setgprp_cache) || die;
eval <$fh> || die; eval <$fh> || die;
close $fh; close $fh;

View file

@ -742,6 +742,11 @@ par_unquote_replacement_string() {
parallel echo '{}{=uq()=}' ::: '`echo foo`' parallel echo '{}{=uq()=}' ::: '`echo foo`'
} }
par_delimiter_space() {
echo '### Does space as delimiter work?'
parallel -d " " echo ::: "1 done"
}
export -f $(compgen -A function | grep par_) export -f $(compgen -A function | grep par_)
compgen -A function | grep par_ | LC_ALL=C sort | compgen -A function | grep par_ | LC_ALL=C sort |

View file

@ -331,18 +331,26 @@ par_do_not_export_PARALLEL_ENV() {
par_nice() { par_nice() {
echo 'Check that --nice works' echo 'Check that --nice works'
# parallel-20160422 OK # parallel-20160422 OK
check_for_2_bzip2s() {
perl -e '
for(1..5) {
# Try 5 times if the machine is slow starting bzip2
sleep(1);
@out = qx{ps -eo "%c %n" | grep 18 | grep bzip2};
if($#out == 1) {
# Should find 2 lines
print @out;
exit 0;
}
}
print "failed\n@out";
'
}
# wait for load < 8 # wait for load < 8
parallel --load 8 echo ::: load_10 parallel --load 8 echo ::: load_10
parallel -j0 --timeout 10 --nice 18 bzip2 '<' ::: /dev/zero /dev/zero & parallel -j0 --timeout 10 --nice 18 bzip2 '<' ::: /dev/zero /dev/zero &
pid=$! pid=$!
# Should find 2 lines check_for_2_bzip2s
# Try 5 times if the machine is slow starting bzip2
(sleep 1; ps -eo "%c %n" | grep 18 | grep bzip2) ||
(sleep 1; ps -eo "%c %n" | grep 18 | grep bzip2) ||
(sleep 1; ps -eo "%c %n" | grep 18 | grep bzip2) ||
(sleep 1; ps -eo "%c %n" | grep 18 | grep bzip2) ||
(sleep 1; ps -eo "%c %n" | grep 18 | grep bzip2) ||
(sleep 1; ps -eo "%c %n" | grep 18 | grep bzip2)
parallel --retries 10 '! kill -TERM' ::: $pid 2>/dev/null parallel --retries 10 '! kill -TERM' ::: $pid 2>/dev/null
} }

View file

@ -95,6 +95,9 @@ par_delimiter line 3
par_delimiter delimiter TAB line 1 par_delimiter delimiter TAB line 1
par_delimiter line 2 par_delimiter line 2
par_delimiter line 3 par_delimiter line 3
par_delimiter_space ### Does space as delimiter work?
par_delimiter_space 1
par_delimiter_space done
par_disk_full ### Disk full par_disk_full ### Disk full
par_disk_full cat: write error: No space left on device par_disk_full cat: write error: No space left on device
par_disk_full parallel: Error: Output is incomplete. par_disk_full parallel: Error: Output is incomplete.