]> git.eshelyaron.com Git - emacs.git/commitdiff
mapconcat fast path with `identity` function argument
authorMattias Engdegård <mattiase@acm.org>
Wed, 14 Sep 2022 16:46:40 +0000 (18:46 +0200)
committerMattias Engdegård <mattiase@acm.org>
Thu, 15 Sep 2022 07:40:08 +0000 (09:40 +0200)
This makes (mapconcat #'identity SEQ) slightly faster than
(apply #'concat SEQ), which used to be much faster.
Notably, `string-join` benefits from this change as it uses mapconcat.

* src/fns.c (Fmapconcat): Speed up execution when the function
argument is `identity`.

src/fns.c

index 2f4808be3d0a59cc55ad17ceb03d566ffaa39f6e..9dd10fe44389e522179dec2ad9701dac3503602d 100644 (file)
--- a/src/fns.c
+++ b/src/fns.c
@@ -2930,15 +2930,37 @@ FUNCTION must be a function of one argument, and must return a value
     return empty_unibyte_string;
   Lisp_Object *args;
   SAFE_ALLOCA_LISP (args, args_alloc);
+  if (EQ (function, Qidentity))
+    {
+      /* Fast path when no function call is necessary.  */
+      if (CONSP (sequence))
+       {
+         Lisp_Object src = sequence;
+         Lisp_Object *dst = args;
+         do
+           {
+             *dst++ = XCAR (src);
+             src = XCDR (src);
+           }
+         while (!NILP (src));
+         goto concat;
+       }
+      else if (VECTORP (sequence))
+       {
+         memcpy (args, XVECTOR (sequence)->contents, leni * sizeof *args);
+         goto concat;
+       }
+    }
   ptrdiff_t nmapped = mapcar1 (leni, args, function, sequence);
-  ptrdiff_t nargs = 2 * nmapped - 1;
   eassert (nmapped == leni);
 
+ concat: ;
+  ptrdiff_t nargs = args_alloc;
   if (NILP (separator) || (STRINGP (separator) && SCHARS (separator) == 0))
-    nargs = nmapped;
+    nargs = leni;
   else
     {
-      for (ptrdiff_t i = nmapped - 1; i > 0; i--)
+      for (ptrdiff_t i = leni - 1; i > 0; i--)
         args[i + i] = args[i];
 
       for (ptrdiff_t i = 1; i < nargs; i += 2)