Lazyweb Request: Profiling Timer Expired?

Dear Lazyweb:

I have a bash script with a while loop that takes a long time to process. It restores file modification times for complicated reasons not worth discussing here. Removing some nonessential stuff, I have the following code (I know it could be rewritten to be elegant, or at least collapsed into a single line):

``
cat ./preserve_file_mod_times | while read x
do
  filename=`echo $x|sed 's/|.*//g'`
  lastmod=`echo $x|sed 's/^.*|//g'`
  touch -t "$lastmod" "$filename"
done
``

As the input file has gotten longer, the loop now frequently fails:

376 Profiling timer expired touch -t "$lastmod" "$filename"

I’ve googled this error and understand what it is (i.e. SIGPROF) but not how to fix or workaround it. Any hints?

Thanks!

7 comments

  1. Giuseppe Sacco Aug 14

    What shell are you using? Has it been compiled with gprof? Anyway, I would try trapping the signal and ignoring it, as in:
    trap “” SIGPROF

    Bye,
    Giuseppe

  2. adam Aug 14

    Using bash. Your fix worked, thanks!

  3. adam Aug 14

    (bash from Debian Stable — don’t know if it’s built with gprof or not)

  4. Simon Aug 14

    At the risk of ignoring your original comments on elegance.

    Why not set “IFS” to “|”

    I assume from the sed statement that “|” doesn’t occur in the data except as a delimiter.

    IFS=”|”
    while read filename lastmod
    do
    touch -t “$lastmod” “$filename”
    done <test.txt

    Markdown code indent not work

    Eliminating 2N+1 processes which hopefully will speed it up somewhat.

    Of course if other code in the loop relies on IFS you need to ensure it is scoped correctly.

  5. Jan Hudec Aug 15

    Even not using IFS, the echo $x|sed ... can be replaced with ${x#…} and ${x%…} constructs like:

    filename=${x%%|*}
    lastmod=${x##*|}
    

    (and you can of course avoid the temporary variables, but they would be good for debugging). It should be faster and more portable — echo is not compatible between bash and dash.

    Also I suggest using dash instead of bash if you can do without the couple extra bash features as dash seems to be quite a bit faster.

  6. adam Aug 15

    Great suggestions!

    Run-times:

    Original script (bash): 391 seconds

    Original script (dash): 379 seconds

    Original script, using Simon’s IFS trick (dash): 109 seconds

  7. Jason Lewis Aug 16

    By the way, back ticks “ are no longer recommended and one should use $() instead in bash. A moot point given Jan suggestion.

Leave a Reply

(Markdown Syntax Permitted)