cut: make memory allocation independent of range width
commit3e466ad05181d95057e6612ff11059c91396cd0e
authorCojocaru Alexandru <xojoc@gmx.com>
Sun, 9 Dec 2012 09:43:10 +0000 (9 10:43 +0100)
committerPádraig Brady <P@draigBrady.com>
Mon, 29 Apr 2013 16:54:27 +0000 (29 17:54 +0100)
tree2110ad15ceb663c914eb61edb50d0df5408f4866
parente414ff4c4c3fe029a9702c9909bf4eccbef68c21
cut: make memory allocation independent of range width

The current implementation of cut, uses a bit array,
an array of `struct range_pair's, and (when --output-delimiter
is specified) a hash_table.  The new implementation will use
only an array of `struct range_pair's.
The old implementation is memory inefficient because:
 1. When -b with a big num is specified, it allocates a lot of
    memory for `printable_field'.
 2. When --output-delimiter is specified, it will allocate 31 buckets.
    Even if only a few ranges are specified.

Note CPU overhead is increased to determine if an item is to be printed,
as shown by:

$ yes abcdfeg | head -n1MB > big-file
$ for c in with-bitarray without-bitarray; do
    src/cut-$c 2>/dev/null
    echo -ne "\n== $c =="
    time src/cut-$c -b1,3 big-file > /dev/null
  done

== with-bitarray ==
real    0m0.084s
user    0m0.078s
sys     0m0.006s

== without-bitarray ==
real    0m0.111s
user    0m0.108s
sys     0m0.002s

Subsequent patches will reduce this overhead.

* src/cut.c (set_fields): Set and initialize RP
instead of printable_field.
* src/cut.c (is_range_start_index): Use CURRENT_RP rather than a hash.
* tests/misc/cut.pl: Check if `eol_range_start' is set correctly.
* tests/misc/cut-huge-range.sh: Rename from cut-huge-to-eol-range.sh,
and add a test to verify large amounts of mem aren't allocated.
Fixes http://bugs.gnu.org/13127
src/cut.c
tests/local.mk
tests/misc/cut-huge-range.sh [moved from tests/misc/cut-huge-to-eol-range.sh with 84% similarity]
tests/misc/cut.pl