git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 2/2] optimize compat/ memmem()

From
René Scharfe <rene.scharfe@lsrfire.ath.cx>
Date
Mar 2, 2009, 23:19 UTC
Message-ID
<49AC6982.6000804@lsrfire.ath.cx>
In-Reply-To
<49AC6527.5010808@lsrfire.ath.cx>

When memmem() was imported from glibc 2.2 into compat/, an optimization was dropped in the process, in order to make the code smaller and simpler. It was OK because memmem() wasn't used in performance-critical code. Now the situation has changed and we can benefit from this optimization.

The trick is to avoid calling memcmp() if the first character of the needle already doesn't match. Checking one character directly is much cheaper than the function call overhead. We keep the first character of the needle in the variable named point and the rest in the one named tail.

The following commands were run in a Linux kernel repository and timed, the best of five results is shown:

  $ STRING='Ensure that the real time constraints are schedulable.'
  $ git log -S"$STRING" HEAD -- kernel/sched.c >/dev/null
On Windows Vista x64, before:
  real    0m8.470s
  user    0m0.000s
  sys     0m0.000s
And after the patch:
  real    0m1.887s
  user    0m0.000s
  sys     0m0.000s
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
---
This performance fix is a good idea, even if we later decide to import
the latest version of memmem() from Gnulib, I think.  And I'm not so
sure any more that we want to do that in the first place.  More
measurements are needed (which goes for these two patches, too, of
course), but this version should provide a better baseline.
 compat/memmem.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/compat/memmem.c b/compat/memmem.c
index cd0d877..56bcb42 100644
--- a/compat/memmem.c
+++ b/compat/memmem.c
@@ -5,6 +5,8 @@ void *gitmemmem(const void *haystack, size_t haystack_len,
 {
 	const char *begin = haystack;
 	const char *last_possible = begin + haystack_len - needle_len;
+	const char *tail = needle;
+	char point;
 
 	/*
 	 * The first occurrence of the empty string is deemed to occur at
@@ -20,8 +22,9 @@ void *gitmemmem(const void *haystack, size_t haystack_len,
 	if (haystack_len < needle_len)
 		return NULL;
 
+	point = *tail++;
 	for (; begin <= last_possible; begin++) {
-		if (!memcmp(begin, needle, needle_len))
+		if (*begin == point && !memcmp(begin + 1, tail, needle_len - 1))
 			return (void *)begin;
 	}
 
-- 
1.6.2.rc2
Previous: René Scharfe
Message 23 of 23 in “Pickaxe search clean-up and optimization”
  1. 0/4 Pickaxe search clean-up and optimizationJunio C Hamano, Feb 26, 2009
  2. 1/4 diffcore-pickaxe: refactor diffcore_pickaxe()Junio C Hamano, Feb 26, 2009
  3. René ScharfeFeb 27, 2009
  4. 2/4 diffcore-pickaxe: micro-optimize has_match() functionJunio C Hamano, Feb 26, 2009
  5. 3/4 diffcore-pickaxe: further refactor count_match()Junio C Hamano, Feb 26, 2009
  6. Kjetil BarvikFeb 26, 2009
  7. René ScharfeFeb 28, 2009
  8. Junio C HamanoFeb 28, 2009
  9. Junio C HamanoFeb 28, 2009
  10. René ScharfeFeb 28, 2009
  11. Junio C HamanoFeb 28, 2009
  12. René ScharfeFeb 28, 2009
  13. import memmem() with linear complexity from GnulibRené Scharfe, Feb 28, 2009
  14. Mike HommeyFeb 28, 2009
  15. Jeff KingMar 1, 2009
  16. René ScharfeMar 1, 2009
  17. René ScharfeMar 1, 2009
  18. Junio C HamanoMar 1, 2009
  19. René ScharfeMar 1, 2009
  20. 4/4 diffcore-pickaxe: optimize by trimming common initial and trailing partsJunio C Hamano, Feb 26, 2009
  21. Junio C HamanoFeb 26, 2009
  22. 1/2 diffcore-pickaxe: use memmem()René Scharfe, Mar 2, 2009
  23. 2/2 optimize compat/ memmem()René Scharfe, Mar 2, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.