Merge "utils: Add FastStrcmp.h" am: 0f8890d985 am: dcd44168d3 am: 54890a929c
am: 41c99f83d9

Change-Id: Ic0d10a2a6536a75c5d99345475135418fc943380
diff --git a/include/utils/FastStrcmp.h b/include/utils/FastStrcmp.h
new file mode 100644
index 0000000..3844e7d
--- /dev/null
+++ b/include/utils/FastStrcmp.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014-2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_UTILS_FASTSTRCMP_H__
+#define _ANDROID_UTILS_FASTSTRCMP_H__
+
+#ifdef __cplusplus
+
+// Optimized for instruction cache locality
+//
+// Template class fastcmp used to create more time-efficient str*cmp
+// functions by pre-checking the first character before resorting
+// to calling the underlying string function.  Profiled with a
+// measurable speedup when used in hot code.  Usage is of the form:
+//
+//  fastcmp<strncmp>(str1, str2, len)
+//
+// NB: Does not work for the case insensitive str*cmp functions.
+// NB: Returns boolean, do not use if expecting to check negative value.
+//     Thus not semantically identical to the expected function behavior.
+
+template <int (*cmp)(const char *l, const char *r, const size_t s)>
+static inline int fastcmp(const char *l, const char *r, const size_t s) {
+    return (*l != *r) || cmp(l + 1, r + 1, s - 1);
+}
+
+template <int (*cmp)(const void *l, const void *r, const size_t s)>
+static inline int fastcmp(const void *lv, const void *rv, const size_t s) {
+    const char *l = static_cast<const char *>(lv);
+    const char *r = static_cast<const char *>(rv);
+    return (*l != *r) || cmp(l + 1, r + 1, s - 1);
+}
+
+template <int (*cmp)(const char *l, const char *r)>
+static inline int fastcmp(const char *l, const char *r) {
+    return (*l != *r) || cmp(l + 1, r + 1);
+}
+
+#endif
+
+#endif // _ANDROID_UTILS_FASTSTRCMP_H__
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index f5c60c7..ec91f2a 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -89,7 +89,7 @@
         size_t name_len = strlen(name);
         // KISS: ToDo: Only checks prefix truncated, not suffix, or both
         if ((retval_len < name_len)
-                && !fast<strcmp>(retval, name + name_len - retval_len)) {
+                && !fastcmp<strcmp>(retval, name + name_len - retval_len)) {
             free(retval);
             retval = name;
         } else {
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index 7073535..0b49fc1 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -321,7 +321,7 @@
                 }
                 --len;
             } while (*s++ != c);
-        } while (fast<memcmp>(s, needle, needleLen));
+        } while (fastcmp<memcmp>(s, needle, needleLen));
         s--;
     }
     return s;
@@ -640,7 +640,7 @@
 
     static const char infoBrace[] = "[INFO]";
     static const size_t infoBraceLen = strlen(infoBrace);
-    if ((taglen >= infoBraceLen) && !fast<strncmp>(p, infoBrace, infoBraceLen)) {
+    if ((taglen >= infoBraceLen) && !fastcmp<strncmp>(p, infoBrace, infoBraceLen)) {
         // <PRI>[<TIME>] "[INFO]"<tag> ":" message
         bt = p + infoBraceLen;
         taglen -= infoBraceLen;
@@ -675,7 +675,7 @@
             p = cp + 1;
         } else if ((taglen > size) && (tolower(*bt) == tolower(*cp))) {
             // clean up any tag stutter
-            if (!fast<strncasecmp>(bt + 1, cp + 1, size - 1)) { // no match
+            if (!fastcmp<strncasecmp>(bt + 1, cp + 1, size - 1)) { // no match
                 // <PRI>[<TIME>] <tag> <tag> : message
                 // <PRI>[<TIME>] <tag> <tag>: message
                 // <PRI>[<TIME>] <tag> '<tag>.<num>' : message
@@ -697,8 +697,8 @@
                 static const char host[] = "_host";
                 static const size_t hostlen = strlen(host);
                 if ((size > hostlen) &&
-                        !fast<strncmp>(bt + size - hostlen, host, hostlen) &&
-                        !fast<strncmp>(bt + 1, cp + 1, size - hostlen - 1)) {
+                        !fastcmp<strncmp>(bt + size - hostlen, host, hostlen) &&
+                        !fastcmp<strncmp>(bt + 1, cp + 1, size - hostlen - 1)) {
                     const char *b = cp;
                     cp += size - hostlen;
                     taglen -= size - hostlen;
@@ -746,10 +746,10 @@
         // register names like x18 but not driver names like en0
             || ((size == 3) && (isdigit(tag[1]) && isdigit(tag[2])))
         // blacklist
-            || ((size == cpuLen) && !fast<strncmp>(tag, cpu, cpuLen))
-            || ((size == warningLen) && !fast<strncasecmp>(tag, warning, warningLen))
-            || ((size == errorLen) && !fast<strncasecmp>(tag, error, errorLen))
-            || ((size == infoLen) && !fast<strncasecmp>(tag, info, infoLen))) {
+            || ((size == cpuLen) && !fastcmp<strncmp>(tag, cpu, cpuLen))
+            || ((size == warningLen) && !fastcmp<strncasecmp>(tag, warning, warningLen))
+            || ((size == errorLen) && !fastcmp<strncasecmp>(tag, error, errorLen))
+            || ((size == infoLen) && !fastcmp<strncasecmp>(tag, info, infoLen))) {
         p = start;
         etag = tag = "";
     }
@@ -761,7 +761,7 @@
     const char *mp = strnrchr(tag, ']', taglen);
     if (mp && (++mp < etag)) {
         size_t s = etag - mp;
-        if (((s + s) < taglen) && !fast<memcmp>(mp, mp - 1 - s, s)) {
+        if (((s + s) < taglen) && !fastcmp<memcmp>(mp, mp - 1 - s, s)) {
             taglen = mp - tag;
         }
     }
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index 61d4c49..1b50b4e 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -108,7 +108,7 @@
     }
 
     bool nonBlock = false;
-    if (!fast<strncmp>(buffer, "dumpAndClose", 12)) {
+    if (!fastcmp<strncmp>(buffer, "dumpAndClose", 12)) {
         // Allow writer to get some cycles, and wait for pending notifications
         sched_yield();
         LogTimeEntry::lock();
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index d4b48ef..bab87ba 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -53,7 +53,7 @@
             if (ret > 0) {
                 buffer[sizeof(buffer)-1] = '\0';
                 // frameworks intermediate state
-                if (fast<strcmp>(buffer, "<pre-initialized>")) {
+                if (fastcmp<strcmp>(buffer, "<pre-initialized>")) {
                     retval = strdup(buffer);
                 }
             }
@@ -209,7 +209,7 @@
             if (nameTmp) {
                 if (!name) {
                     name = strdup(nameTmp);
-                } else if (fast<strcmp>(name, nameTmp)) {
+                } else if (fastcmp<strcmp>(name, nameTmp)) {
                     free(const_cast<char *>(name));
                     name = NULL;
                     break;
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 1f598af..cb7ae2b 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -307,7 +307,7 @@
     const char*getName() const { return name; }
 
     inline void add(pid_t newPid) {
-        if (name && !fast<strncmp>(name, "zygote", 6)) {
+        if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
             free(name);
             name = NULL;
         }
@@ -368,7 +368,7 @@
     const char*getName() const { return name; }
 
     inline void add(pid_t incomingTid) {
-        if (name && !fast<strncmp>(name, "zygote", 6)) {
+        if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
             free(name);
             name = NULL;
         }
diff --git a/logd/LogUtils.h b/logd/LogUtils.h
index 44ac742..ec68062 100644
--- a/logd/LogUtils.h
+++ b/logd/LogUtils.h
@@ -20,6 +20,7 @@
 #include <sys/cdefs.h>
 #include <sys/types.h>
 
+#include <utils/FastStrcmp.h>
 #include <private/android_logger.h>
 #include <sysutils/SocketClient.h>
 
@@ -50,21 +51,4 @@
             (id == LOG_ID_RADIO) || (id == LOG_ID_EVENTS);
 }
 
-template <int (*cmp)(const char *l, const char *r, const size_t s)>
-static inline int fast(const char *l, const char *r, const size_t s) {
-    return (*l != *r) || cmp(l + 1, r + 1, s - 1);
-}
-
-template <int (*cmp)(const void *l, const void *r, const size_t s)>
-static inline int fast(const void *lv, const void *rv, const size_t s) {
-    const char *l = static_cast<const char *>(lv);
-    const char *r = static_cast<const char *>(rv);
-    return (*l != *r) || cmp(l + 1, r + 1, s - 1);
-}
-
-template <int (*cmp)(const char *l, const char *r)>
-static inline int fast(const char *l, const char *r) {
-    return (*l != *r) || cmp(l + 1, r + 1);
-}
-
 #endif // _LOGD_LOG_UTILS_H__