bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [bug-gnulib] Re: speed up gnulib-tool a bit


From: Bruno Haible
Subject: Re: [bug-gnulib] Re: speed up gnulib-tool a bit
Date: Mon, 18 Sep 2006 17:20:14 +0200
User-agent: KMail/1.9.1

Ralf Wildenhues wrote:
> Hmm, ok.  But traditional shells execute this construct
>   while read foo
>   do
>     $whatever
>   done <$file
> 
> in a subshell, too, for example Solaris 10 sh.

Ouch. Looking at the variables, it indeed behaves like a subshell.
Looking at the process id, it does not...!

$ cat script.sh 
echo $$
echo foo > foo
var="initial value"
while read foo
do
  echo foo $$
  var="set by code inside while"
done < foo
echo $$
echo "var = $var"

$ /bin/sh script.sh 
3908
foo 3908
3908
var = initial value

$ /usr/xpg4/bin/sh script.sh
3910
foo 3910
3910
var = set by code inside while

> To be safe, I think you 
> need to `exec <$file', or, restoring stdin, something like this:
>   exec 5<&1 <$file
>   while read r
>   do
>     $whatever
>   done
>   exec <&5 5<&-

Astonishing. I never saw this kind of low-level shell programming.
Applied; see attached patch.

> > Where can I download the shell script profiler that you used?
> 
> Hehe.  Several crude methods, plus some experience with huge shell
> scripts: Either take a slow terminal emulator and watch `sh -x script'
> fly by, or dump its output, and pipe it through
>   sort | uniq -c | sort -k1n
> 
> wher both the short tail and any long, similar regions are interesting.

Thanks for all these tips!

> I think it may be possible to shave off another good part, but the next
> changes probably have a higher source code change to improvement ratio
> (caching func_lookup_file results could help; or rewriting func_get_*
> to work on lists of modules; both seem like not too high hanging fruit).

Uhh, I would be a bit reluctant to apply the second type of changes, since
it changes the program structure for no other reason than speed. The major
bottleneck at this time are the autom4te / m4 invocations after gnulib-tool.
(I'm turning off autom4te's caching in my ~/.autom4te.cfg since temporary
directories would be acceptable for me in /tmp, but not in the middle
of my source code directories.)

Caching func_lookup_file results would be acceptable.

Bruno


*** gnulib-tool 18 Sep 2006 13:07:37 -0000      1.165
--- gnulib-tool 18 Sep 2006 15:13:46 -0000
***************
*** 1672,1688 ****
    LC_ALL=C join -t"$delimiter" -v2 "$tmp"/old-files "$tmp"/new-files \
      | sed -e "$sed_take_last_column" \
      | sed -e "s,^.*\$,&$delimiter&," -e "$sed_rewrite_new_files" > 
"$tmp"/added-files
!   while read g f; do
!     func_add_or_update
!   done < "$tmp"/added-files
    # Then the files that are in new-files and in old-files:
    already_present=true
    LC_ALL=C join -t"$delimiter" "$tmp"/old-files "$tmp"/new-files \
      | sed -e "$sed_take_last_column" \
      | sed -e "s,^.*\$,&$delimiter&," -e "$sed_rewrite_new_files" > 
"$tmp"/kept-files
!   while read g f; do
!     func_add_or_update
!   done < "$tmp"/kept-files
  
    # Command-line invocation printed in a comment in generated gnulib-cache.m4.
    actioncmd="gnulib-tool --import"
--- 1672,1698 ----
    LC_ALL=C join -t"$delimiter" -v2 "$tmp"/old-files "$tmp"/new-files \
      | sed -e "$sed_take_last_column" \
      | sed -e "s,^.*\$,&$delimiter&," -e "$sed_rewrite_new_files" > 
"$tmp"/added-files
!   { # Rearrange file descriptors. Needed because "while ... done < ..."
!     # constructs are executed in a subshell e.g. by Solaris 10 /bin/sh.
!     exec 5<&1 < "$tmp"/added-files
!     while read g f; do
!       func_add_or_update
!     done
!     exec 1<&5 5<&-
!   }
    # Then the files that are in new-files and in old-files:
    already_present=true
    LC_ALL=C join -t"$delimiter" "$tmp"/old-files "$tmp"/new-files \
      | sed -e "$sed_take_last_column" \
      | sed -e "s,^.*\$,&$delimiter&," -e "$sed_rewrite_new_files" > 
"$tmp"/kept-files
!   { # Rearrange file descriptors. Needed because "while ... done < ..."
!     # constructs are executed in a subshell e.g. by Solaris 10 /bin/sh.
!     exec 5<&1 < "$tmp"/kept-files
!     while read g f; do
!       func_add_or_update
!     done
!     exec 1<&5 5<&-
!   }
  
    # Command-line invocation printed in a comment in generated gnulib-cache.m4.
    actioncmd="gnulib-tool --import"
***************
*** 2069,2087 ****
      | sed -e "s,^.*\$,&$delimiter&," -e "$sed_rewrite_files" \
      | LC_ALL=C sort \
      > "$tmp"/files
!   while read g f; do
!     func_lookup_file "$f"
!     if test -n "$lookedup_tmp"; then
!       cp -p "$lookedup_file" "$testdir/$g"
!     else
!       ln "$lookedup_file" "$testdir/$g" 2>/dev/null ||
!       if test -z "$symbolic"; then
          cp -p "$lookedup_file" "$testdir/$g"
        else
!         ln -s "$lookedup_file" "$testdir/$g"
        fi
!     fi
!   done < "$tmp"/files
  
    # Create $sourcebase/Makefile.am.
    mkdir -p "$testdir/$sourcebase"
--- 2079,2102 ----
      | sed -e "s,^.*\$,&$delimiter&," -e "$sed_rewrite_files" \
      | LC_ALL=C sort \
      > "$tmp"/files
!   { # Rearrange file descriptors. Needed because "while ... done < ..."
!     # constructs are executed in a subshell e.g. by Solaris 10 /bin/sh.
!     exec 5<&1 < "$tmp"/files
!     while read g f; do
!       func_lookup_file "$f"
!       if test -n "$lookedup_tmp"; then
          cp -p "$lookedup_file" "$testdir/$g"
        else
!         ln "$lookedup_file" "$testdir/$g" 2>/dev/null ||
!         if test -z "$symbolic"; then
!           cp -p "$lookedup_file" "$testdir/$g"
!         else
!           ln -s "$lookedup_file" "$testdir/$g"
!         fi
        fi
!     done
!     exec 1<&5 5<&-
!   }
  
    # Create $sourcebase/Makefile.am.
    mkdir -p "$testdir/$sourcebase"




reply via email to

[Prev in Thread] Current Thread [Next in Thread]