Platinum Partner
architects,devops,tips and tricks,tools & methods,bash

Fork Less in Bash and See Performance Wins

So, if you haven’t seen this page you should take a look. It has a whole bunch of interesting techniques you can use to manipulate strings in bash. If you end up working with bash a lot you might find yourself doing this quite a bit, since it can save a lot of time.

Let's take a pretty typical task, stripping the domain off of an email address.

So this poorly written program will split an email address at the first @ and print the first portion:

#!/bin/bash
i=0
while test $i -lt 1000; do
	STRING="foo@bar.com"
	echo ${STRING} | awk -F@ '{print $1}'
	i=$(($i+1))
done

Its counterpart, which does not fork, uses a bash built-in to remove everything after the @:

#!/bin/bash
i=0
while test $i -lt 1000; do
	STRING="foo@bar.com"
	echo ${STRING%%@*}
	i=$(($i+1))
done

So, what's the execution difference?

$ time bash with_awk_split.sh > /dev/null
 
real	0m3.737s
user	0m0.196s
sys	0m0.556s
 
$ time bash with_bash_split.sh > /dev/null
 
real	0m0.034s
user	0m0.020s
sys	0m0.012s

It's 100x faster to skip the fork.

Now, granted this is a pretty dumb example, and it's easy to rewrite this to perform better than the bash example (i.e. don’t use a loop and just use awk which is 3x faster than the pure bash solution). So, think about what your doing, use a pipe over a loop, and if you can’t do that, try to find a built-in that can take care of your needs.

Published at DZone with permission of {{ articles[0].authors[0].realName }}, DZone MVB. (source)

Opinions expressed by DZone contributors are their own.

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}