unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Making `replace-match' more efficient
@ 2021-10-07 18:33 Lars Ingebrigtsen
  2021-10-07 18:54 ` Eli Zaretskii
  0 siblings, 1 reply; 3+ messages in thread
From: Lars Ingebrigtsen @ 2021-10-07 18:33 UTC (permalink / raw)
  To: emacs-devel

We use `replace-match' a lot in our code (either directly or
indirectly), and I was poking at it to see whether there's any obvious
opportunities to make it faster, and immediately found a way to make
`replace-regexp-in-string' 10% faster in the by just checking whether
the replacement contains any backslashes or not.  (It's f2bd2386a79.)

So I poked at it some more, and thought that the exploratory patch below
seemed like an obvious way to make it generate less garbage, but the
performance impact was exactly zero, so I ditched that.

But it still seems like there's still opportunities for making it faster
in many common cases.  For instance, the most popular REPLACE string is
"", which should be exploitable...

Anyway, I'm just posting this here in case it inspires somebody to
explore.

diff --git a/src/search.c b/src/search.c
index 08f1e9474f..5471e05c0f 100644
--- a/src/search.c
+++ b/src/search.c
@@ -2501,9 +2501,6 @@ DEFUN ("replace-match", Freplace_match, Sreplace_match, 1, 5, 0,
     {
       Lisp_Object before, after;
 
-      before = Fsubstring (string, make_fixnum (0), make_fixnum (sub_start));
-      after = Fsubstring (string, make_fixnum (sub_end), Qnil);
-
       /* Substitute parts of the match into NEWTEXT
 	 if desired.  */
       if (NILP (literal))
@@ -2598,6 +2595,30 @@ DEFUN ("replace-match", Freplace_match, Sreplace_match, 1, 5, 0,
       else if (case_action == cap_initial)
 	newtext = Fupcase_initials (newtext);
 
+      if (SBYTES (string) == SCHARS (string)
+	  && SBYTES (newtext) == SCHARS (newtext)
+	  && !string_intervals (string)
+	  && !string_intervals (newtext))
+	{
+	  char *conc;
+	  ptrdiff_t len = sub_start + SBYTES (newtext) +
+	    SBYTES (string) - sub_end;
+
+	  conc = xmalloc (len);
+	  memcpy (conc, SSDATA (string), sub_start);
+	  memcpy (conc + sub_start, SSDATA (newtext), SBYTES (newtext));
+	  memcpy (conc + sub_start + SBYTES (newtext),
+		  SSDATA (string) + sub_end,
+		  SBYTES (string) - sub_end);
+	  Lisp_Object result = make_unibyte_string (conc, len);
+
+	  xfree (conc);
+	  return result;
+	}
+      
+      before = Fsubstring (string, make_fixnum (0), make_fixnum (sub_start));
+      after = Fsubstring (string, make_fixnum (sub_end), Qnil);
+
       return concat3 (before, newtext, after);
     }
 

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-10-07 18:56 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-10-07 18:33 Making `replace-match' more efficient Lars Ingebrigtsen
2021-10-07 18:54 ` Eli Zaretskii
2021-10-07 18:56   ` Lars Ingebrigtsen

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).