21

I had an idea to quickly benchmark some decompression programs. E.g. for gz, I would run the command:

timeout 10 zcat foo.gz | wc -c

Which would measure the amount of data the decompressor could extract in 10 seconds.

The only problem is, that it does not work: as zcat is killed, wc is also killed, so I do not get the byte count, just a Terminated message.

So, the question is: is there a way to get the count from wc, either by blocking the signal somehow, or use an alternative instead of wc that prints a result even when it gets a term signal.


Of course, there are alternatives:

  1. Writing to a temporary file:
    timeout 10 zcat foo.gz > /dev/shm/x ; du -sb /dev/shm/x ; rm -r /dev/shm/x The problem with this is that is uses a lot of memory, and also may have some performance penalty.

  2. Using ulimit instead:
    ulimit -t 10; zcat foo.gz | wc -c
    This also works, but measures only cpu time, so slowdown due to I/O (e.g. because the compression is worse, and more bytes need to be read from disk) is not measured.

  3. Making smaller test files:
    Well, this can work of course, and may be the nicest solution. However, this creates a lot of temporary files.

1
  • 6
    As I read "breaking pipes and wc" I thought at first you were having problems with your plumbing!
    – dr_
    Sep 23, 2015 at 22:11

3 Answers 3

22

You can place the timeout command in a subshell and make it succeed:

( timeout 10 <command> || true ) | wc -c
3
  • 3
    Making a failed command succeed? Oh, this looks so evil :D
    – Erathiel
    Sep 23, 2015 at 10:58
  • 19
    @Erathiel Wanna smile while being evil? Try this one (it's equivalent to the above): (timeout 10 <command> || :) | wc -c
    – Marco
    Sep 23, 2015 at 11:02
  • 1
    I tried using a subshell, but did not think about making it succeed. Excellent!
    – P.Péter
    Sep 23, 2015 at 11:08
2

Just after posting, I had a thought to use named pipes for the process:

mkfifo /tmp/x; wc -c /tmp/x & timeout 10 zcat foo.gz > /tmp/x &

This seems to work.

0

You can also use the timeout --foreground option, to make timeout only consider the immediate process and not the whole process group associated with the pipeline

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .