Производительность C++, оптимизирующий компилятор, пустая функция в .cpp

Я имею очень простой класс, называю его Основным, используемым почти во всех других файлах в большем проекте. В некоторых случаях должен быть вывод отладки, но в режиме выпуска, это не должно быть включено и быть NOOP.

В настоящее время в заголовке существует определение, который включает макрос или прочь, в зависимости от установки. Таким образом, это - определенно NOOP при выключении. Я задаюсь вопросом, если у меня есть следующий код, если компилятор (MSVS / gcc) может оптимизировать вызов функции, так, чтобы это был снова NOOP. (Путем выполнения этого переключатель мог быть в .cpp, и переключение будет намного быстрее, компилировать/связывать мудрое время).

--Header--
void printDebug(const Basic* p);

class Basic {
   Basic() {
      simpleSetupCode;

      // this should be a NOOP in release, 
      // but constructor could be inlined
      printDebug(this);
   }
};
--Source--
// PRINT_DEBUG defined somewhere else or here
#if PRINT_DEBUG
void printDebug(const Basic* p) {
   // Lengthy debug print
}
#else
void printDebug(const Basic* p) {}
#endif
5
задан Dodo 4 May 2010 в 08:32
поделиться

5 ответов

Как и на все подобные вопросы, ответ таков: если это действительно важно для вас, попробуйте подход и изучите выпущенный язык ассемблера.

2
ответ дан 15 December 2019 в 00:54
поделиться

В настоящее время большая часть оптимизаций выполняется во время компиляции. Некоторые компиляторы, такие как LLVM , могут выполнять оптимизацию во время компоновки. Это действительно интересная идея. Предлагаю вам взглянуть.

Ожидая такой оптимизации, вы можете сделать следующее. Определите макрос, который позволит вам включить следующий оператор в зависимости от того, определена ли DEBUG или нет.

#ifdef DEBUG
#define IF_DEBUG (false) {} else
#else
#define IF_DEBUG 
#endif

Вы можете использовать его так

   Basic() {
      simpleSetupCode;

      // this should be a NOOP in release, 
      // but constructor could be inlined
      IF_DEBUG printDebug(this);
   }

, который уже намного удобнее, чем

   Basic() {
      simpleSetupCode;

      // this should be a NOOP in release, 
      // but constructor could be inlined
#if DEBUG
      printDebug(this);
#endif
   }

Обратите внимание, что вы можете использовать его, как если бы это было ключевое слово

IF_DEBUG {
   printDebug(this);
   printDebug(thas);
}
0
ответ дан 15 December 2019 в 00:54
поделиться
#if PRINT_DEBUG
#define printDebug _real_print_debug
#else
#define printDebug(...)
#endif

Таким образом, препроцессор удалит весь отладочный код еще до того, как он попадет в компилятор.

1
ответ дан 15 December 2019 в 00:54
поделиться

Компилятор, возможно, может оптимизировать этот код, если он знает реализацию функции printDebug во время компиляции. Если printDebug находится в другом объектном модуле, это, возможно, может быть оптимизировано только компоновщиком, используя оптимизацию всей программы. Но единственный способ проверить это - прочитать код сборки, созданный компилятором. Если у вас уже есть макрос PRINT_DEBUG, вы можете расширить его, как определено TRACE:

#define PRINT_DEBUG    // optional
#ifdef PRINT_DEBUG
#define PRINT_DEBUG_CALL(p) printDebug(p)
#else
#define PRINT_DEBUG_CALL(p)
#endif


void printDebug(const Basic* p);

class Basic {
   Basic() {
      simpleSetupCode;

      // this should be a NOOP in release, 
      // but constructor could be inlined
      PRINT_DEBUG_CALL(this);
   }
};
--Source--
// PRINT_DEBUG defined somewhere else or here
#if PRINT_DEBUG
void printDebug(const Basic* p) {
   // Lengthy debug print
}
#endif
1
ответ дан 15 December 2019 в 00:54
поделиться

эээ, почему бы не использовать макрос препроцессора по-другому?

Просто в голове, что-то вроде:

  #define DEBUG_TRACE(p)
  #ifdef PRINT_DEBUG
    printDebug(p);
  #else
    ;
  #endif
0
ответ дан 15 December 2019 в 00:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: