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.

P.Péter
  • 525
  • 3
  • 12
  • 6
    As I read "breaking pipes and wc" I thought at first you were having problems with your plumbing! – dr_ Sep 23 '15 at 22:11

3 Answers3

22

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

( timeout 10 <command> || true ) | wc -c
Marco
  • 33,188
  • 10
  • 112
  • 146
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.

P.Péter
  • 525
  • 3
  • 12
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

Pádraig Brady
  • 3,063
  • 1
  • 23
  • 13