This patch is incomplete, but it is mostly to demonstrate something
interesting I noticed. It looks like 'join' spends a large portion of
it's time in iswblank even when LC_ALL=C.

The easiest way to see this is with widely separated fields, as shown
in the commit message. Note that 'join -t' can likely be optimized
with some inspiration from bytesearch_field_delim_ok in src/cut.c.

-- 8< --

    $ export LC_ALL=C
    $ seq 10000000 | perl -ple '$_ = $_ . (" " x 100) . $_' \
        | LC_ALL=C sort >file1
    $ seq 20000000 | perl -ple '$_ = $_ . (" " x 100) . $_' \
        | LC_ALL=C sort >file2
    $ time ./src/join file1 file2 > /dev/null

    real        0m6.216s
    user        0m5.458s
    sys         0m0.714s
    $ time join file1 file2 > /dev/null

    real        0m14.260s
    user        0m13.537s
    sys         0m0.655s

* src/join.c (xfields): Prefer strspn and strcspn in ASCII locales.
---
 src/join.c | 32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/src/join.c b/src/join.c
index 4346758a6..4c3c1829a 100644
--- a/src/join.c
+++ b/src/join.c
@@ -323,12 +323,32 @@ xfields (struct line *line)
     return;
 
   if (!tab.len)
-    while ((ptr = skip_buf_matching (ptr, lim, newline_or_blank, true)) < lim)
-      {
-        char *sep = skip_buf_matching (ptr, lim, newline_or_blank, false);
-        extract_field (line, ptr, sep - ptr);
-        ptr = sep;
-      }
+    {
+      if (MB_CUR_MAX <= 1)
+        {
+          do
+            {
+              char *start = ptr + strspn (ptr, "\n\t ");
+              char *end = start + strcspn (start, "\n\t ");
+              idx_t const len = end - start;
+              if (0 < len)
+                extract_field (line, start, len);
+              ptr = end + (ptr < lim);
+            }
+          while (ptr < lim);
+        }
+      else
+        {
+          while ((ptr = skip_buf_matching (ptr, lim, newline_or_blank, true))
+                 < lim)
+            {
+              char *sep = skip_buf_matching (ptr, lim, newline_or_blank,
+                                             false);
+              extract_field (line, ptr, sep - ptr);
+              ptr = sep;
+            }
+        }
+    }
   else
     {
       if (tab.ch != '\n')
-- 
2.55.0


Reply via email to