Use likely()/unlikely() macros to improve branch prediction.

This commit is contained in:
Simon Ruderich
2013-06-10 06:06:00 +02:00
parent 9862b8c8f1
commit 048bd6f9e7
5 changed files with 56 additions and 14 deletions

View File

@@ -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],

View File

@@ -1,5 +1,6 @@
lib_LTLIBRARIES = libcoloredstderr.la
libcoloredstderr_la_SOURCES = coloredstderr.c \
compiler.h \
constants.h \
debug.h \
hookmacros.h \

View File

@@ -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();
}

32
src/compiler.h Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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

View File

@@ -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;