]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
cut: reduce CPU overhead in determining item to output
authorCojocaru Alexandru <xojoc@gmx.com>
Sun, 28 Apr 2013 02:03:45 +0000 (03:03 +0100)
committerPádraig Brady <P@draigBrady.com>
Mon, 29 Apr 2013 16:54:39 +0000 (17:54 +0100)
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
tests/misc/cut-huge-range.sh

index 8738c46a010598c06f78584a59591cec3ded19f2..37615a34a48d16fb8fec0b78822779c1e2fba1a5 100644 (file)
--- 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)
             {
index 8783e96ad59f494627a5f45c905c7630775acd21..887197ae9e078a993c1a15213ece3cc016915c53 100755 (executable)
@@ -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.