Stories
Slash Boxes
Comments

SoylentNews is people

SoylentNews is powered by your submissions, so send in your scoop. Only 17 submissions in the queue.
posted by Fnord666 on Sunday August 25 2019, @01:57PM   Printer-friendly
from the quite-the-contrary dept.

Submitted via IRC for SoyCow3196

Why const Doesn't Make C Code Faster

In a post a few months back I said it's a popular myth that const is helpful for enabling compiler optimisations in C and C++. I figured I should explain that one, especially because I used to believe it was obviously true, myself. I'll start off with some theory and artificial examples, then I'll do some experiments and benchmarks on a real codebase: Sqlite.

Let's start with what I used to think was the simplest and most obvious example of how const can make C code faster. First, let's say we have these two function declarations:

void func(int *x);
void constFunc(const int *x);

And suppose we have these two versions of some code:

void byArg(int *x)
{
  printf("%d\n", *x);
  func(x);
  printf("%d\n", *x);
}

void constByArg(const int *x)
{
  printf("%d\n", *x);
  constFunc(x);
  printf("%d\n", *x);
}

To do the printf(), the CPU has to fetch the value of *x from RAM through the pointer. Obviously, constByArg() can be made slightly faster because the compiler knows that *x is constant, so there's no need to load its value a second time after constFunc() does its thing. It's just printing the same thing. Right? Let's see the assembly code generated by GCC with optimisations cranked up:


Original Submission

 
This discussion has been archived. No new comments can be posted.
Display Options Threshold/Breakthrough Mark All as Read Mark All as Unread
The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
  • (Score: 3, Insightful) by maxwell demon on Sunday August 25 2019, @08:35PM (3 children)

    by maxwell demon (1608) on Sunday August 25 2019, @08:35PM (#885361) Journal

    I didn't have to look at the compiler output to know that the compiler cannot use const for optimization in this case. Just my general C and C++ knowledge.

    Let's look at the code:

    void constFunc(const int *x);

    void constByArg(const int *x)
    {
      printf("%d\n", *x);
      constFunc(x);
      printf("%d\n", *x);
    }

    So what does this tell the compiler? Well, it tells the compiler that the function constByArg gets a pointer to a potentially constant integer, and that it should not modify that integer through that pointer. It then passes the pointer on to constFunc which makes the same promise.

    However while compiling constByArg, the compiler does not know where the variable comes from, and in particular not whether it is really const, nor whether constFunc can change that variable by other means. For example, another translation unit might contain the following code:

    int var; // NOT const!

    void constFunc(const int *x)
    {
      var++; // legal! Does not attempt to change *x, not even through a typecast
    }

    int main()
    {
      var = 42;
      constByArg(&var);
    }

    That program is 100% legal code, and is required to output

    42
    43

    In other words, if the compiler made the optimizations the author was obviously expecting, it would not conform to the standard.

    But anyway, const isn't even meant as an optimization tool, it is meant as a tool to help with ensuring correctness of code. Just like the compiler will flag as error any attempts to multiply a pointer by 2, even though on about every modern architecture the pointer just contains a number, the compiler will also flag the attempt to modify a value through pointers to const. And just like you can bypass the first error with typecasts, you also can bypass the second error. A typecast is basically telling the compiler "I know what I'm doing, so don't complain". Of course if you do not know what you are doing, your code may blow up. But hey, if you disable the safety mechanisms, that's what you have to expect (just ask the people who operated the Chernobyl reactor!).

    --
    The Tao of math: The numbers you can count are not the real numbers.
    Starting Score:    1  point
    Moderation   +1  
       Insightful=1, Total=1
    Extra 'Insightful' Modifier   0  
    Karma-Bonus Modifier   +1  

    Total Score:   3  
  • (Score: -1, Redundant) by Anonymous Coward on Sunday August 25 2019, @11:13PM (1 child)

    by Anonymous Coward on Sunday August 25 2019, @11:13PM (#885412)

    void constFunc(const int *x)
    {
        var++; // legal! Does not attempt to change *x, not even through a typecast
    }

    Assuming you got the function names wrong by accident, and you meant to put in two printfs, no shit? You weren't doing an operation on *x.

    However, if you read *x, a const int *, you would have seen the value change.

    • (Score: 2) by maxwell demon on Sunday August 25 2019, @11:25PM

      by maxwell demon (1608) on Sunday August 25 2019, @11:25PM (#885418) Journal

      I did not get the function names wrong. If you look at the complete post, you'll find the call of constFunc, as well as the two printf calls.

      --
      The Tao of math: The numbers you can count are not the real numbers.
  • (Score: 2) by FatPhil on Monday August 26 2019, @07:51AM

    by FatPhil (863) <{pc-soylent} {at} {asdf.fi}> on Monday August 26 2019, @07:51AM (#885559) Homepage
    Not that you can't create counter-examples without, perhaps we should also be teaching programmers the evils of global variables, so that when the simplest counter-examples such as yours (yet, apparently, too complex for the AC to understand - what is the correct moderation for such a useless post?) are shown the young programmer knows that evil was being invoked during the process of breaking things.

    In order for const to help provide what newbs thinks const provides, you also need to teach them restrict and __attr__((pure)) (and thefore that in order to achieve their goals they need to escape the core language, and rely on individual implementations instead), and then hammer into them the fact that if you do end up with the desired optimisations it's only a side effect of what you've actually concretely got - namely an instruction that *you* are not permitted to alter the pointed-to object (via that pointer, modulo "restrict").

    It was a bad choice of word, and we're stuck with it, but that doesn't mean it's a bad concept, despite what some of the neighsayers are braying on about above.
    --
    Great minds discuss ideas; average minds discuss events; small minds discuss people; the smallest discuss themselves