Changed implementation of logging macros.

We have observed some strange performance-related behavior as described here: https://stackoverflow.com/questions/29652787/adding-stringstream-cout-hurts-performance-even-when-the-code-is-never-called

This set of changes addresses this problem. The old macros would simply expand the logging code in place, whereas we now have logging functions and the macros call these. Overall I believe it is tidier.
This commit is contained in:
David Williams
2015-05-07 22:58:00 +02:00
parent 4dadbbffd1
commit f16a247934
6 changed files with 156 additions and 288 deletions

View File

@ -116,40 +116,26 @@ freely, subject to the following restrictions:
* ...
*/
#ifdef POLYVOX_THROW_ENABLED
namespace PolyVox
{
template< typename ExceptionType, typename ... Args >
void polyvox_throw(Args const& ... messageArgs)
{
std::string message = Impl::argListToString(messageArgs...);
#ifdef POLYVOX_LOG_ERROR_ENABLED
PolyVox::Impl::getLoggerInstance()->logErrorMessage(message);
#endif
throw ExceptionType(message);
}
#define POLYVOX_THROW_IF(condition, type, message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do \
{ \
if ((condition)) \
{ \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logErrorMessage(ss.str()); \
throw type(ss.str()); \
} \
} while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_THROW(type, message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do \
{ \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logErrorMessage(ss.str()); \
throw type(ss.str()); \
} while(0) \
POLYVOX_MSC_WARNING_POP
template< typename ExceptionType, typename ... Args >
void polyvox_throw_if(bool condition, Args const& ... messageArgs)
{
if(condition) { polyvox_throw<ExceptionType>(messageArgs...); }
}
}
#define POLYVOX_THROW(type, ...) PolyVox::polyvox_throw<type>(__VA_ARGS__)
#define POLYVOX_THROW_IF(condition, type, ...) PolyVox::polyvox_throw_if<type>(condition, __VA_ARGS__)
#else
namespace PolyVox
{

View File

@ -81,270 +81,152 @@ namespace PolyVox
{
Impl::getLoggerInstance() = pLogger;
}
namespace Impl
{
// Used for building the log messages - convert a list of variables into a string.
// Based on second approach here: http://stackoverflow.com/a/25386444/2337254
template< typename ... Args >
std::string argListToString(const Args& ... args)
{
std::ostringstream oss;
int a[] = { 0, ((void)(oss << args), 0) ... };
(void)a; // Prevent warnings about unused param
return oss.str();
}
// Log trace message
template< typename ... Args >
void logTraceMessage(Args const& ... messageArgs)
{
std::string message = argListToString(messageArgs...);
PolyVox::Impl::getLoggerInstance()->logTraceMessage(message);
}
template< typename ... Args >
void logTraceMessageIf(bool condition, Args const& ... messageArgs)
{
if (condition) { logTraceMessage(messageArgs...); }
}
// Log debug message
template< typename ... Args >
void logDebugMessage(Args const& ... messageArgs)
{
std::string message = argListToString(messageArgs...);
PolyVox::Impl::getLoggerInstance()->logDebugMessage(message);
}
template< typename ... Args >
void logDebugMessageIf(bool condition, Args const& ... messageArgs)
{
if (condition) { logDebugMessage(messageArgs...); }
}
// Log info message
template< typename ... Args >
void logInfoMessage(Args const& ... messageArgs)
{
std::string message = argListToString(messageArgs...);
PolyVox::Impl::getLoggerInstance()->logInfoMessage(message);
}
template< typename ... Args >
void logInfoMessageIf(bool condition, Args const& ... messageArgs)
{
if (condition) { logInfoMessage(messageArgs...); }
}
// Log warning message
template< typename ... Args >
void logWarningMessage(Args const& ... messageArgs)
{
std::string message = argListToString(messageArgs...);
PolyVox::Impl::getLoggerInstance()->logWarningMessage(message);
}
template< typename ... Args >
void logWarningMessageIf(bool condition, Args const& ... messageArgs)
{
if (condition) { logWarningMessage(messageArgs...); }
}
// Log error message
template< typename ... Args >
void logErrorMessage(Args const& ... messageArgs)
{
std::string message = argListToString(messageArgs...);
PolyVox::Impl::getLoggerInstance()->logErrorMessage(message);
}
template< typename ... Args >
void logErrorMessageIf(bool condition, Args const& ... messageArgs)
{
if (condition) { logErrorMessage(messageArgs...); }
}
// Log fatal message
template< typename ... Args >
void logFatalMessage(Args const& ... messageArgs)
{
std::string message = argListToString(messageArgs...);
PolyVox::Impl::getLoggerInstance()->logFatalMessage(message);
}
template< typename ... Args >
void logFatalMessageIf(bool condition, Args const& ... messageArgs)
{
if (condition) { logFatalMessage(messageArgs...); }
}
}
}
#ifdef POLYVOX_LOG_TRACE_ENABLED
#define POLYVOX_LOG_TRACE(message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do \
{ \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logTraceMessage(ss.str()); \
} while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_TRACE_IF(condition, message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do \
{ \
if ((condition)) \
{ \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logTraceMessage(ss.str()); \
} \
} while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_TRACE(...) PolyVox::Impl::logTraceMessage(__VA_ARGS__)
#define POLYVOX_LOG_TRACE_IF(condition, ...) PolyVox::Impl::logTraceMessageIf(condition, __VA_ARGS__)
#else
// We don't bother with the do...while(0) construct here as we're not executing multiple statements
// We also don't bother with forcing variables to be 'used'. If this causes a problem then calling
// code can just force them to be used itself in addition to calling the logging macro. Basically
// we just want to reduce the chance of extra code being generated.
#define POLYVOX_LOG_TRACE(message)
#define POLYVOX_LOG_TRACE_IF(condition, message)
#define POLYVOX_LOG_TRACE(...)
#define POLYVOX_LOG_TRACE_IF(condition, ...)
#endif
#ifdef POLYVOX_LOG_DEBUG_ENABLED
#define POLYVOX_LOG_DEBUG(message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do \
{ \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logDebugMessage(ss.str()); \
} while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_DEBUG_IF(condition, message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do \
{ \
if ((condition)) \
{ \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logDebugMessage(ss.str()); \
} \
} while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_DEBUG(...) PolyVox::Impl::logDebugMessage(__VA_ARGS__)
#define POLYVOX_LOG_DEBUG_IF(condition, ...) PolyVox::Impl::logDebugMessageIf(condition, __VA_ARGS__)
#else
// We don't bother with the do...while(0) construct here as we're not executing multiple statements
// We also don't bother with forcing variables to be 'used'. If this causes a problem then calling
// code can just force them to be used itself in addition to calling the logging macro. Basically
// we just want to reduce the chance of extra code being generated.
#define POLYVOX_LOG_DEBUG(message)
#define POLYVOX_LOG_DEBUG_IF(condition, message)
#define POLYVOX_LOG_DEBUG(...)
#define POLYVOX_LOG_DEBUG_IF(condition, ...)
#endif
#ifdef POLYVOX_LOG_INFO_ENABLED
#define POLYVOX_LOG_INFO(message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do \
{ \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logInfoMessage(ss.str()); \
} while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_INFO_IF(condition, message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do \
{ \
if ((condition)) \
{ \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logInfoMessage(ss.str()); \
} \
} while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_INFO(...) PolyVox::Impl::logInfoMessage(__VA_ARGS__)
#define POLYVOX_LOG_INFO_IF(condition, ...) PolyVox::Impl::logInfoMessageIf(condition, __VA_ARGS__)
#else
// We don't bother with the do...while(0) construct here as we're not executing multiple statements
// We also don't bother with forcing variables to be 'used'. If this causes a problem then calling
// code can just force them to be used itself in addition to calling the logging macro. Basically
// we just want to reduce the chance of extra code being generated.
#define POLYVOX_LOG_INFO(message)
#define POLYVOX_LOG_INFO_IF(condition, message)
#define POLYVOX_LOG_INFO(...)
#define POLYVOX_LOG_INFO_IF(condition, ...)
#endif
#ifdef POLYVOX_LOG_WARNING_ENABLED
#define POLYVOX_LOG_WARNING(message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do \
{ \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logWarningMessage(ss.str()); \
} while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_WARNING_IF(condition, message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do \
{ \
if ((condition)) \
{ \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logWarningMessage(ss.str()); \
} \
} while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_WARNING(...) PolyVox::Impl::logWarningMessage(__VA_ARGS__)
#define POLYVOX_LOG_WARNING_IF(condition, ...) PolyVox::Impl::logWarningMessageIf(condition, __VA_ARGS__)
#else
// We don't bother with the do...while(0) construct here as we're not executing multiple statements
// We also don't bother with forcing variables to be 'used'. If this causes a problem then calling
// code can just force them to be used itself in addition to calling the logging macro. Basically
// we just want to reduce the chance of extra code being generated.
#define POLYVOX_LOG_WARNING(message)
#define POLYVOX_LOG_WARNING_IF(condition, message)
#define POLYVOX_LOG_WARNING(...)
#define POLYVOX_LOG_WARNING_IF(condition, ...)
#endif
#ifdef POLYVOX_LOG_ERROR_ENABLED
#define POLYVOX_LOG_ERROR(message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do \
{ \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logErrorMessage(ss.str()); \
} while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_ERROR_IF(condition, message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do \
{ \
if ((condition)) \
{ \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logErrorMessage(ss.str()); \
} \
} while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_ERROR(...) PolyVox::Impl::logErrorMessage(__VA_ARGS__)
#define POLYVOX_LOG_ERROR_IF(condition, ...) PolyVox::Impl::logErrorMessageIf(condition, __VA_ARGS__)
#else
// We don't bother with the do...while(0) construct here as we're not executing multiple statements
// We also don't bother with forcing variables to be 'used'. If this causes a problem then calling
// code can just force them to be used itself in addition to calling the logging macro. Basically
// we just want to reduce the chance of extra code being generated.
#define POLYVOX_LOG_ERROR(message)
#define POLYVOX_LOG_ERROR_IF(condition, message)
#define POLYVOX_LOG_ERROR(...)
#define POLYVOX_LOG_ERROR_IF(condition, ...)
#endif
#ifdef POLYVOX_LOG_FATAL_ENABLED
#define POLYVOX_LOG_FATAL(message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do \
{ \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logFatalMessage(ss.str()); \
} while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_FATAL_IF(condition, message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do \
{ \
if ((condition)) \
{ \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logFatalMessage(ss.str()); \
} \
} while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_FATAL(...) PolyVox::Impl::logFatalMessage(__VA_ARGS__)
#define POLYVOX_LOG_FATAL_IF(condition, ...) PolyVox::Impl::logFatalMessageIf(condition, __VA_ARGS__)
#else
// We don't bother with the do...while(0) construct here as we're not executing multiple statements
// We also don't bother with forcing variables to be 'used'. If this causes a problem then calling
// code can just force them to be used itself in addition to calling the logging macro. Basically
// we just want to reduce the chance of extra code being generated.
#define POLYVOX_LOG_FATAL(message)
#define POLYVOX_LOG_FATAL_IF(condition, message)
#define POLYVOX_LOG_FATAL(...)
#define POLYVOX_LOG_FATAL_IF(condition, ...)
#endif
#endif //__PolyVox_Logging_H__