From 048bd6f9e7f316aafede310ba273776d0086b8ed Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Mon, 10 Jun 2013 06:06:00 +0200 Subject: [PATCH] Use likely()/unlikely() macros to improve branch prediction. --- configure.ac | 8 ++++++++ src/Makefile.am | 1 + src/coloredstderr.c | 9 +++++---- src/compiler.h | 32 ++++++++++++++++++++++++++++++++ src/hookmacros.h | 20 ++++++++++---------- 5 files changed, 56 insertions(+), 14 deletions(-) create mode 100644 src/compiler.h diff --git a/configure.ac b/configure.ac index 6248625..ec5b658 100644 --- a/configure.ac +++ b/configure.ac @@ -47,6 +47,14 @@ AC_C_INLINE AC_FUNC_FORK AC_CHECK_FUNCS([dup2 memmove setenv strdup]) +dnl Thanks to gperftools' configure.ac (https://code.google.com/p/gperftools). +AC_MSG_CHECKING([for __builtin_expect]) +AC_LINK_IFELSE([AC_LANG_PROGRAM([],[return __builtin_expect(main != 0, 1)])], + [AC_DEFINE([HAVE___BUILTIN_EXPECT], 1, + [Define to 1 if the compiler supports __builtin_expect().]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) + AC_SEARCH_LIBS([dlsym], [dl], [], [AC_MSG_ERROR([dlsym() is required])]) AC_ARG_ENABLE([debug], diff --git a/src/Makefile.am b/src/Makefile.am index b62b114..1526e1d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,6 @@ lib_LTLIBRARIES = libcoloredstderr.la libcoloredstderr_la_SOURCES = coloredstderr.c \ + compiler.h \ constants.h \ debug.h \ hookmacros.h \ diff --git a/src/coloredstderr.c b/src/coloredstderr.c index a95486d..72a881f 100644 --- a/src/coloredstderr.c +++ b/src/coloredstderr.c @@ -51,6 +51,7 @@ static int force_write_to_non_tty; #include "constants.h" +#include "compiler.h" #ifdef DEBUG # include "debug.h" #endif @@ -68,7 +69,7 @@ static void dup_fd(int oldfd, int newfd) { debug("%3d -> %3d\t\t\t[%d]\n", oldfd, newfd, getpid()); #endif - if (!initialized) { + if (unlikely(!initialized)) { init_from_environment(); } @@ -90,7 +91,7 @@ static void close_fd(int fd) { debug("%3d -> .\t\t\t[%d]\n", fd, getpid()); #endif - if (!initialized) { + if (unlikely(!initialized)) { init_from_environment(); } @@ -124,7 +125,7 @@ inline static void init_pre_post_string(void) { static void handle_fd_pre(int fd) { int saved_errno = errno; - if (!pre_string || !post_string) { + if (unlikely(!pre_string || !post_string)) { init_pre_post_string(); } @@ -145,7 +146,7 @@ static void handle_fd_post(int fd) { static void handle_file_pre(FILE *stream) { int saved_errno = errno; - if (!pre_string || !post_string) { + if (unlikely(!pre_string || !post_string)) { init_pre_post_string(); } diff --git a/src/compiler.h b/src/compiler.h new file mode 100644 index 0000000..3d92f2f --- /dev/null +++ b/src/compiler.h @@ -0,0 +1,32 @@ +/* + * Compiler specific macros. + * + * Copyright (C) 2013 Simon Ruderich + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef COMPILER_H +#define COMPILER_H 1 + +/* Branch prediction information for the compiler. */ +#ifdef HAVE___BUILTIN_EXPECT +# define likely(x) __builtin_expect(!!(x), 1) +# define unlikely(x) __builtin_expect(!!(x), 0) +#else +# define likely(x) x +# define unlikely(x) x +#endif + +#endif diff --git a/src/hookmacros.h b/src/hookmacros.h index 35e6470..0eb47cd 100644 --- a/src/hookmacros.h +++ b/src/hookmacros.h @@ -56,10 +56,10 @@ #define _HOOK_PRE(type, name) \ int handle; \ - if (!(real_ ## name )) { \ + if (unlikely(!(real_ ## name ))) { \ *(void **) (&(real_ ## name)) = dlsym_function(#name); \ /* Initialize our data while we're at it. */ \ - if (!initialized) { \ + if (unlikely(!initialized)) { \ init_from_environment(); \ } \ } @@ -68,8 +68,8 @@ _HOOK_PRE_FD_(type, name, fd) #define _HOOK_PRE_FD_(type, name, fd) \ _HOOK_PRE(type, name) \ - if (tracked_fds_find(fd)) { \ - if (force_write_to_non_tty) { \ + if (unlikely(tracked_fds_find(fd))) { \ + if (unlikely(force_write_to_non_tty)) { \ handle = 1; \ } else { \ handle = isatty(fd); \ @@ -77,14 +77,14 @@ } else { \ handle = 0; \ } \ - if (handle) { \ + if (unlikely(handle)) { \ handle_fd_pre(fd); \ } #define _HOOK_PRE_FILE(type, name, file) \ type result; \ _HOOK_PRE(type, name) \ - if (tracked_fds_find(fileno(file))) { \ - if (force_write_to_non_tty) { \ + if (unlikely(tracked_fds_find(fileno(file)))) { \ + if (unlikely(force_write_to_non_tty)) { \ handle = 1; \ } else { \ handle = isatty(fileno(file)); \ @@ -92,18 +92,18 @@ } else { \ handle = 0; \ } \ - if (handle) { \ + if (unlikely(handle)) { \ handle_file_pre(file); \ } #define _HOOK_POST_FD_(fd) \ - if (handle) { \ + if (unlikely(handle)) { \ handle_fd_post(fd); \ } #define _HOOK_POST_FD(fd) \ _HOOK_POST_FD_(fd) \ return result; #define _HOOK_POST_FILE(file) \ - if (handle) { \ + if (unlikely(handle)) { \ handle_file_post(file); \ } \ return result; -- 2.45.2