我可以依靠我的编译器来优化const char *上的strlen吗?
在我的SAX xml解析回调(XCode 4,LLVM)中,我正在对这种类型的代码进行大量调用:
static const char* kFoo = "Bar"; void SaxCallBack(char* sax_string,.....) { if ( strcmp(sax_string, kFoo, strlen(kFoo) ) == 0) { } }
假设strlen(kFoo)由编译器优化是否安全?
(Apple示例代码已经预先计算了strlen(kFoo),但我认为这对于大量常量字符串很容易出错。)
编辑:优化的动机:使用NSXMLParser在iPod touch 2G上解析我的SVG地图需要5秒钟(!)。 所以,我想切换到lib2xml,并优化字符串比较。
如果通过“LLVM”你的意思是铿锵,那么是的,你可以依靠clang -O
来优化strlen
。 以下是您的函数的代码:
_SaxCallBack: Leh_func_begin1: pushq %rbp Ltmp0: movq %rsp, %rbp Ltmp1: leaq L_.str1(%rip), %rsi movl $3, %edx callq _strncmp ...
我将strcmp
更改为strncmp
,但第三个参数确实被直接的$3
取代。
请注意,gcc 4.2.1 -O3不会优化此strlen
调用,并且您只能期望它在您的问题的精确条件下工作(尤其是字符串和对strlen
的调用必须位于同一文件中)。
不要写像这样的东西:
static const char* kFoo = "Bar";
您已经创建了一个名为kFoo
的变量 ,它指向常量数据。 编译器可能能够检测到此变量不会更改并优化它,但如果没有,则会使程序的数据段膨胀。
也不要写像:
static const char *const kFoo = "Bar";
现在你的变量kFoo
是const
限定的且不可修改的,但如果它用于位置无关的代码(共享库等),那么内容在运行时仍然会有所不同,因此它会为你的程序增加启动和内存成本。 相反,使用:
static const char kFoo[] = "Bar";
甚至:
#define kFoo "Bar"
一般来说,你不能指望它。 但是,您可以使用’sizeof’并将其应用于字符串文字。 当然,这意味着您不能像最初定义的那样定义’kFoo’。
以下内容适用于所有编译器和所有优化级别。
#define kFoo "..." ... strcmp(... sizeof(kFoo))
后续问题:
你测试过以下的吗?
static std::string const kFoo = "BAR"; void SaxCallBack(char* sax_string,.....) { if ( sax_string == kFoo) { } }
这是可读性的净赢,但我不知道性能成本。
作为替代方案,如果您必须自己发送,我发现使用类似状态机的方法(使用堆栈)可读性更好,并且也可能在性能方面获胜(而不是使用大量标签)开启你只有现在可以满足的标签)。