diff options
author | Cojocaru Alexandru <xojoc@gmx.com> | 2013-04-28 03:03:45 +0100 |
---|---|---|
committer | Pádraig Brady <P@draigBrady.com> | 2013-04-29 17:54:39 +0100 |
commit | ef9db5735a401f60eb5b4a18a365bf1ece525053 (patch) | |
tree | 836c6d92830d2fa3037e2378e4277dc634bb81ef | |
parent | 3e466ad05181d95057e6612ff11059c91396cd0e (diff) | |
download | coreutils-ef9db5735a401f60eb5b4a18a365bf1ece525053.tar.xz |
cut: reduce CPU overhead in determining item to output
print_kth() is the central function of cut used to
determine if an item is to be output or not,
so simplify it by moving some logic outside.
Benchmark results for this change are:
$ yes abcdfeg | head -n1MB > big-file
$ for c in orig split; do
src/cut-$c 2>/dev/null
echo -ne "\n== $c =="
time src/cut-$c -b1,3 big-file > /dev/null
done
== orig ==
real 0m0.111s
user 0m0.108s
sys 0m0.002s
== split ==
real 0m0.088s
user 0m0.081s
sys 0m0.007s
* src/cut.c (print_kth): Refactor a branch to outside the function.
Related to http://bugs.gnu.org/13127
-rw-r--r-- | src/cut.c | 54 | ||||
-rwxr-xr-x | tests/misc/cut-huge-range.sh | 2 |
2 files changed, 27 insertions, 29 deletions
@@ -233,6 +233,20 @@ With no FILE, or when FILE is -, read standard input.\n\ exit (status); } +/* Return nonzero if the K'th field or byte is printable. */ + +static bool +print_kth (size_t k) +{ + bool k_selected = false; + if (0 < eol_range_start && eol_range_start <= k) + k_selected = true; + else if (current_rp->lo <= k && k <= current_rp->hi) + k_selected = true; + + return k_selected ^ complement; +} + /* Return nonzero if K'th byte is the beginning of a range. */ static inline bool @@ -248,24 +262,6 @@ is_range_start_index (size_t k) return is_start; } -/* Return nonzero if the K'th field or byte is printable. */ - -static bool -print_kth (size_t k, bool *range_start) -{ - bool k_selected = false; - if (0 < eol_range_start && eol_range_start <= k) - k_selected = true; - else if (current_rp->lo <= k && k <= current_rp->hi) - k_selected = true; - - bool is_selected = k_selected ^ complement; - if (range_start && is_selected) - *range_start = is_range_start_index (k); - - return k_selected ^ complement; -} - /* Comparison function for qsort to order the list of struct range_pairs. */ static int @@ -491,16 +487,18 @@ cut_bytes (FILE *stream) else { next_item (&byte_idx); - bool range_start; - bool *rs = output_delimiter_specified ? &range_start : NULL; - if (print_kth (byte_idx, rs)) + if (print_kth (byte_idx)) { - if (rs && *rs && print_delimiter) + if (output_delimiter_specified) { - fwrite (output_delimiter_string, sizeof (char), - output_delimiter_length, stdout); + if (print_delimiter && is_range_start_index (byte_idx)) + { + fwrite (output_delimiter_string, sizeof (char), + output_delimiter_length, stdout); + } + print_delimiter = true; } - print_delimiter = true; + putchar (c); } } @@ -532,7 +530,7 @@ cut_fields (FILE *stream) and the first field has been selected, or if non-delimited lines must be suppressed and the first field has *not* been selected. That is because a non-delimited line has exactly one field. */ - buffer_first_field = (suppress_non_delimited ^ !print_kth (1, NULL)); + buffer_first_field = (suppress_non_delimited ^ !print_kth (1)); while (1) { @@ -578,7 +576,7 @@ cut_fields (FILE *stream) } continue; } - if (print_kth (1, NULL)) + if (print_kth (1)) { /* Print the field, but not the trailing delimiter. */ fwrite (field_1_buffer, sizeof (char), n_bytes - 1, stdout); @@ -589,7 +587,7 @@ cut_fields (FILE *stream) int prev_c = c; - if (print_kth (field_idx, NULL)) + if (print_kth (field_idx)) { if (found_any_selected_field) { diff --git a/tests/misc/cut-huge-range.sh b/tests/misc/cut-huge-range.sh index 8783e96ad..887197ae9 100755 --- a/tests/misc/cut-huge-range.sh +++ b/tests/misc/cut-huge-range.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Ensure that cut does not allocate mem for a range like -b9999999999999- +# Ensure that cut does not allocate mem for large ranges # Copyright (C) 2012-2013 Free Software Foundation, Inc. |