diff --git a/include/utils/FastStrcmp.h b/include/utils/FastStrcmp.h new file mode 100644 index 000000000..3844e7d96 --- /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(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 +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 +static inline int fastcmp(const void *lv, const void *rv, const size_t s) { + const char *l = static_cast(lv); + const char *r = static_cast(rv); + return (*l != *r) || cmp(l + 1, r + 1, s - 1); +} + +template +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 f5c60c72b..ec91f2a83 100644 --- a/logd/LogBufferElement.cpp +++ b/logd/LogBufferElement.cpp @@ -89,7 +89,7 @@ char *android::tidToName(pid_t tid) { size_t name_len = strlen(name); // KISS: ToDo: Only checks prefix truncated, not suffix, or both if ((retval_len < name_len) - && !fast(retval, name + name_len - retval_len)) { + && !fastcmp(retval, name + name_len - retval_len)) { free(retval); retval = name; } else { diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp index 707353562..0b49fc1b3 100644 --- a/logd/LogKlog.cpp +++ b/logd/LogKlog.cpp @@ -321,7 +321,7 @@ static const char *strnstr(const char *s, size_t len, const char *needle) { } --len; } while (*s++ != c); - } while (fast(s, needle, needleLen)); + } while (fastcmp(s, needle, needleLen)); s--; } return s; @@ -640,7 +640,7 @@ int LogKlog::log(const char *buf, size_t len) { static const char infoBrace[] = "[INFO]"; static const size_t infoBraceLen = strlen(infoBrace); - if ((taglen >= infoBraceLen) && !fast(p, infoBrace, infoBraceLen)) { + if ((taglen >= infoBraceLen) && !fastcmp(p, infoBrace, infoBraceLen)) { // [