1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-02-16 20:33:18 +02:00

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
This commit is contained in:
Cojocaru Alexandru
2013-04-28 03:03:45 +01:00
committed by Pádraig Brady
parent 3e466ad051
commit ef9db5735a
2 changed files with 27 additions and 29 deletions

View File

@@ -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)
{

View File

@@ -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.