[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250407-imp_str_perf-v1-2-ed95d52964a4@quicinc.com>
Date: Mon, 07 Apr 2025 21:15:05 +0800
From: Zijun Hu <zijun_hu@...oud.com>
To: Kees Cook <kees@...nel.org>, Andy Shevchenko <andy@...nel.org>,
Andrew Morton <akpm@...ux-foundation.org>
Cc: Zijun Hu <zijun_hu@...oud.com>, linux-hardening@...r.kernel.org,
linux-kernel@...r.kernel.org, Zijun Hu <quic_zijuhu@...cinc.com>,
"Rob Herring (Arm)" <robh@...nel.org>
Subject: [PATCH 2/2] lib/string: Improve str_has_prefix() performance
From: Zijun Hu <quic_zijuhu@...cinc.com>
str_has_prefix() is frequently invoked to return length of the prefix
string if a string has another string as prefix, but its performance
is degraded by the strlen() loop contained.
Improve its performance by eliminating the strlen() loop.
Link: https://lore.kernel.org/all/20250113234643.GA3631169-robh@kernel.org
Signed-off-by: Zijun Hu <quic_zijuhu@...cinc.com>
Cc: Rob Herring (Arm) <robh@...nel.org>
---
include/linux/string.h | 21 +--------------------
lib/string.c | 33 +++++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 20 deletions(-)
diff --git a/include/linux/string.h b/include/linux/string.h
index e5f7defa277572719e1dbfdd264f3de6ef8544f1..394b76666ece0924c50264aaca39784d5630a2fe 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -533,25 +533,6 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
sizeof(*(obj)) - offsetof(typeof(*(obj)), member)); \
})
-/**
- * str_has_prefix - Test if a string has a given prefix
- * @str: The string to test
- * @prefix: The string to see if @str starts with
- *
- * A common way to test a prefix of a string is to do:
- * strncmp(str, prefix, sizeof(prefix) - 1)
- *
- * But this can lead to bugs due to typos, or if prefix is a pointer
- * and not a constant. Instead use str_has_prefix().
- *
- * Returns:
- * * strlen(@prefix) if @str starts with @prefix
- * * 0 if @str does not start with @prefix
- */
-static __always_inline size_t str_has_prefix(const char *str, const char *prefix)
-{
- size_t len = strlen(prefix);
- return strncmp(str, prefix, len) == 0 ? len : 0;
-}
+size_t str_has_prefix(const char *str, const char *prefix);
#endif /* _LINUX_STRING_H_ */
diff --git a/lib/string.c b/lib/string.c
index ea52c8509328358e436766b1186a82419d45089d..17f1a070b190debc3eaeff6d1ae45b55bae69b29 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -332,6 +332,39 @@ int strncmp(const char *cs, const char *ct, size_t count)
EXPORT_SYMBOL(strncmp);
#endif
+/**
+ * str_has_prefix - Test if a string has a given prefix
+ * @str: The string to test
+ * @prefix: The string to see if @str starts with
+ *
+ * A common way to test a prefix of a string is to do:
+ * strncmp(str, prefix, sizeof(prefix) - 1)
+ *
+ * But this can lead to bugs due to typos, or if prefix is a pointer
+ * and not a constant. Instead use str_has_prefix().
+ *
+ * Returns:
+ * * strlen(@prefix) if @str starts with @prefix
+ * * 0 if @str does not start with @prefix
+ */
+size_t str_has_prefix(const char *str, const char *prefix)
+{
+ const char *p = prefix;
+ unsigned char c1, c2;
+
+ do {
+ c1 = *str++;
+ c2 = *p++;
+
+ if (c1 != c2)
+ return c2 == '\0' ? p - 1 - prefix : 0;
+
+ } while (c2 != '\0');
+
+ return p - 1 - prefix;
+}
+EXPORT_SYMBOL(str_has_prefix);
+
#ifndef __HAVE_ARCH_STRCHR
/**
* strchr - Find the first occurrence of a character in a string
--
2.34.1
Powered by blists - more mailing lists