16

In my SAX xml parsing callback (XCode 4, LLVM), I am doing a lot of calls to this type of code:

static const char* kFoo = "Bar";

void SaxCallBack(char* sax_string,.....)
{
     if ( strcmp(sax_string, kFoo, strlen(kFoo) ) == 0)
     {

     }


  }

Is it safe to assume that strlen(kFoo) is optimized by the compiler?

(The Apple sample code had pre-calculated strlen(kFoo), but I think this is error prone for large numbers of constant strings.)

Edit: Motivation for optimizing: parsing my SVG map on iPod touch 2G takes 5 seconds (!) using NSXMLParser. So, I want to switch to lib2xml, and optimize the string comparisons.

erbridge
  • 1,376
  • 12
  • 27
Jacko
  • 12,665
  • 18
  • 75
  • 126
  • Optimisation advice to beginners: don't. Optimisation advice to experts: not yet. Unless profiling has shown this is where the bottle neck is in your program, I think you shouldn't be worrying about it. – freespace Apr 24 '11 at 13:24
  • 2
    You mean `strncmp`, right? Because you could just use `strcmp` (with two arguments) and it would be equivalent to the condition as currently written. – Pascal Cuoq Apr 24 '11 at 13:28
  • 5
    @freespace The question is "Can I count on my compiler to optimize...?". Unless you think that this advice applies to compilers, I do not see how it is relevant to this question. – Pascal Cuoq Apr 24 '11 at 13:32
  • 2
    It is almost never safe to assume that something will be optimized by a compiler, unless the language standard dictates it or you checked that it worked 10 times before. So my advice is just to check the generated assembly :) – Johan Kotlinski Apr 24 '11 at 13:33
  • If it matters, you can check it. But it won't matter unless that code is called a zillion times in a "real-time" system. And even then, there are propably many places where manual optimizations help more. It's not like those string constants are a hundred words long. –  Apr 24 '11 at 13:40
  • 2
    @Pascal Cuoq it is relevant to the root cause of the question: that Jacko believes it requires opimtising, which is why he is asking if the compiler will do it for him. I believe there is value in understanding when to investigate compiler optimisations, and when to investigate algorithm optimisations, and when to not waste time on optimisation. – freespace Apr 24 '11 at 13:48

4 Answers4

12

If by "LLVM" you mean clang, then yes, you can count on clang -O to optimize the strlen away. Here is what the code for your function looks like:

_SaxCallBack:
Leh_func_begin1:
    pushq   %rbp
Ltmp0:
    movq    %rsp, %rbp
Ltmp1:
    leaq    L_.str1(%rip), %rsi
    movl    $3, %edx
    callq   _strncmp
    ...

I changed the strcmp into strncmp, but the third argument has indeed been replaced by the immediate $3.

Note that gcc 4.2.1 -O3 does not optimize this strlen call, and that you can only expect it to work in the precise conditions of your question (especially, the string and the call to strlen must be in the same file).

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • 1
    I checked the Microsoft compiler. It also optimized the call when using `/O2` optimization. – Mark Wilkins Apr 24 '11 at 13:56
  • 2
    gcc optimises the `strlen()` call away if `kFoo` itself is made `const` (ie. `static const char * const kFoo = "Bar";`). – caf Apr 24 '11 at 14:21
  • `clang version 2.8` doesn't optimize `strlen()` without the second `const` on my machine. – jfs Apr 24 '11 at 16:42
  • GCC 4.5 and higher does optimize it according to a quick test on gcc.godbolt.org: http://goo.gl/c9dgiq – user31389 Jan 20 '16 at 20:57
12

Don't write things like:

static const char* kFoo = "Bar";

You've created a variable named kFoo that points to constant data. The compiler might be able to detect that this variable does not change and optimize it out, but if not, you've bloated your program's data segment.

Also don't write things like:

static const char *const kFoo = "Bar";

Now your variable kFoo is const-qualified and non-modifiable, but if it's used in position independent code (shared libraries etc.), the contents will still vary at runtime and thus it will add startup and memory cost to your program. Instead, use:

static const char kFoo[] = "Bar";

or even:

#define kFoo "Bar"
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 8
    I would not recommend the `#define` option in C++, definitely not! Thanks for the heads up on the pointer issue. – Matthieu M. Apr 26 '11 at 12:01
  • 1
    The question is tagged C, not C++. But yeah, I would prefer the `static const char []` form anyway. – R.. GitHub STOP HELPING ICE Apr 26 '11 at 12:15
  • Why doesn't "static const char kFoo[]" have the position independent code problem? – Joseph Garvin Jul 08 '11 at 02:14
  • 10
    The issue of `static const char *` is that you create an actual variable in the data segment whose *contents* are the address of another static-storage-duration object (the string literal). This value varies depending on the load address, so it must be patched in (via a relocation) at load time. With `static const char []`, the address does not reside in any static-storage-duration object, and code referring to the array can access it via a clean position-independent PC-relative address that's fixed at link time. – R.. GitHub STOP HELPING ICE Jul 08 '11 at 02:27
  • 2
    @R.. As far as I understand, declaring an array on the other hand causes at least GCC to actually copy the entire literal on the stack, chunk by chunk. In that case one has to weigh whether one wants to pay the penalty of code patching or stack allocation. Am I right? – Armen Michaeli Nov 16 '13 at 19:49
  • 3
    @amn: You would be right if we were talking about objects with automatic storage duration, but these have static storage duration. – R.. GitHub STOP HELPING ICE Nov 16 '13 at 19:56
  • Right, missed that. Nevertheless, what do you think about the fact that statically allocated storage, according to C99, is initialized with `0`s? That's a cost to pay as well, is it not? – Armen Michaeli Nov 17 '13 at 14:18
  • Static storage is always initialized. The value makes no difference to cost on any reasonable implementation. – R.. GitHub STOP HELPING ICE Nov 17 '13 at 18:50
2

In general you can't count on it. However, you could use 'sizeof' and apply it to a string literal. Of course, this mean that you can't define 'kFoo' the way it originally was defined.

The following should work on all compilers and on all optimization levels.

#define kFoo "..."

    ... strcmp(... sizeof(kFoo))
Lindydancer
  • 25,428
  • 4
  • 49
  • 68
  • 5
    Note that in this case `sizeof(kFoo) == strlen(kFoo) + 1` (`sizeof` includes the terminating `NUL`) – vladr Apr 06 '12 at 15:51
0

Follow-up question:

Have you tested the following ?

static std::string const kFoo = "BAR";

void SaxCallBack(char* sax_string,.....)
{
  if ( sax_string == kFoo)
  {

  }


}

It's a net win in readability, but I have no idea about the performance cost.

As an alternative, if you must dispatch by yourself, I have found that using a state-machine like approach (with stack) is much better readability-wise, and might also win performance-wise (instead of having a large number of tags to switch on you only have the tags that can be met right now).

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • Thanks, Matthieu. I am looking into a state machine generator called Ragel, which can generate parsers in a number of languages. – Jacko Apr 28 '11 at 13:44