When grep
or sed
are used with the option --extended-regexp
and the pattern {1,9999}
is a part of the regexp that is used, the performance of these commands become low. To be more clear, below are applied few tests.[1] [2]
- The relative performance of
grep -E
,egrep
andsed -E
is almost equal, so only the test that were made withgrep -E
are provided.
Test 1
$ time grep -E '[0-9]{1,99}' < /dev/null
real 0m0.002s
Test 2
$ time grep -E '[0-9]{1,9999}' < /dev/null
> real 0m0.494s
Test 3
$ time grep -E '[0123456789]{1,9999}' < /dev/null > real 21m43.947s
Test 4
$ time grep -E '[0123456789]+' < /dev/null
$ time grep -E '[0123456789]*' < /dev/null
$ time grep -E '[0123456789]{1,}' < /dev/null
$ time grep -P '[0123456789]{1,9999}' < /dev/null
real 0m0.002s
What is the reason of this significant difference of the performance?
[0-9]+
as well)time grep -E '[0-9]{1,99}' </dev/null
vs.time grep -E '[0-9]{1,9999}' </dev/null
. Even with no input, the second command is slow (on 16.04). As expected, omitting-E
and escaping{
and}
behaves the same and replacing-E
with-P
isn't slow (PCRE is a different engine). Most interesting is how much faster[0-9]
is than.
,x
, and even[0123456789]
. With any of those and{1,9999}
,grep
consumes a huge amount of RAM; I haven't dared let it run for more than ~10min.{
}
are'
'
quoted; the shell passes them unchanged togrep
. Anyway,{1,9999}
would be a very fast and simple brace expansion. The shell would just expand it to1 9999
.ps
andtop
to verifygrep
was passed the expected arguments and that it, notbash
, consumes lots of RAM and CPU. I expectgrep
andsed
both use the POSIX regex functions implemented in libc for BRE/ERE matching; I shouldn't really have talked aboutgrep
design specifically, except insofar as thegrep
developers chose to use that library.time grep ... < /dev/null
, so that people don't conflate the actual problem with the data fed togrep
and other extraneous things.