From ef9db5735a401f60eb5b4a18a365bf1ece525053 Mon Sep 17 00:00:00 2001 From: Cojocaru Alexandru Date: Sun, 28 Apr 2013 03:03:45 +0100 Subject: 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 --- src/cut.c | 54 +++++++++++++++++++++----------------------- tests/misc/cut-huge-range.sh | 2 +- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/cut.c b/src/cut.c index 8738c46a0..37615a34a 100644 --- a/src/cut.c +++ b/src/cut.c @@ -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. -- cgit v1.2.3-54-g00ecf