条件NSLog,不降低性能

时间:2012-08-24 04:28:06

标签: objective-c cocoa debugging nslog

bool kDebuggingEnabled = NO;
...
for(i=0; i<length; i++){
 ...
 if (kDebuggingEnabled) {
  NSLog (@"Value of variable # %i",$resultingOptions);
 }
}

每当我的应用程序处于活动状态时,我的代码每次都会检查NSLog的状态。 有没有更好的方法来提高我的代码的性能?

3 个答案:

答案 0 :(得分:5)

您可以使用预处理器宏来打开和关闭日志记录。一个很好的例子是来自Cocoa is My Girlfriend博客的Marcus Zarra的DLog宏。

#ifdef DEBUG
    #define DLog(...) NSLog(@"%s %@", __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
#else
    #define DLog(...) do { } while (0)
#endif

您可以将上述内容放在prefix.pch文件中,然后将NSLog语句替换为DLog语句。您还需要确保在调试版本配置中设置了DEBUG

使用这样的预处理器宏意味着日志代码不会被编译到您的发布版本中,因此日志语句不会受到性能损失。

博客文章还包含一些其他有用的宏来处理断言。

答案 1 :(得分:2)

您有3个选择:

1)如果要在构建时启用/禁用日志。预处理器解决方案是最好的:

// define MY_ENABLE_LOGS in your build settings for the debug configuration only, for example
#ifdef MY_ENABLE_LOGS
#define MYLog(...) NSLog(__VA_ARGS__)
#else
#define MyLog(...) do { } while(0)
#endif

2)如果您希望能够在运行时启用/禁用日志(例如,基于某些隐藏的首选项),您的解决方案可能是最好的。您可以尝试提示编译器稍微优化一下,但是:

// tell the compiler it's unlikely that kDebuggingEnabled will be true
#define MYLog(...) do { if (__builtin_expect(kDebuggingEnabled, 0)) { NSLog(__VA_ARGS__); } } while(0)

3)最后一个选项稍微复杂一点,但可以提供比日志更丰富的信息,而且只取决于您希望提供的日志记录类型。我们的想法是使用带有dtrace的自定义探针(也可以在Instruments中使用)。这仅适用于OS X(不适用于iOS)。例如,请参阅http://www.macresearch.org/tuning-cocoa-applications-using-dtrace-custom-static-probes-and-instruments

请注意,您可以根据需要混合1)和2)。 3)当没有跟踪探测时,意味着几乎为零成本,并且可以提供比简单日志字符串更丰富的信息。

对这些解决方案的一个警告:当未定义MY_ENABLE_LOGS可能会改变您的应用程序行为时,不会评估日志的参数。

答案 2 :(得分:1)

使用预处理器宏来检查您是否正在构建调试:

#if DEBUG
// do stuff
#end

如果预处理器(在编译器之前运行的东西)将DEBUG评估为true,它将保留代码以供编译器编译,但是如果DEBUG不存在或者为假,它将删除该块代码。