Live data from Hacker News

Why Const Doesn't Make C Code Faster

theartofmachinery.com

81–90 of 197 posts

Re: Why Const Doesn't Make C Code Faster

#81
I think the big problem here is that const doesn't really truly say anything about aliasing.

Even excluding casting evils, calling a method with a const pointer only means that the method isn't supposed to change the value. It does not mean that the caller isn't going to change things (particularly from another thread).

The languages are simply too permissible when it comes to what a pointer means and how it can be used.

For const to be optimizable, you'd need to take Rust's approach and make language level guarantees that "You can't do bad things with this". C and C++ missed that boat.

Re: Why Const Doesn't Make C Code Faster

#82
post #76

// x is just a read-only pointer to something that may or may not be a constant void constFunc(const int *x) Is that correct? I read that as “x is a pointer to a const int” If you want “x is a read-only pointer to an int”, you would need void constFunc(int * const x) The article also doesn’t mention the case “x is a read-only pointer to a constant int”. To state that, you would use void constFunc(const int * const x)…

I believe the distinction they’re making is that there is actually no guarantee that the value pointed to by x will remain constant. All this tells you is that you’re not allowed to use x to make the modification.

Consider:

  int foo = 42;
  const int *x = &foo;
  foo = 43;

Re: Why Const Doesn't Make C Code Faster

#84
post #8

I've worked with JavaScript weenies who are in love with the const declaration. They don't have an answer, though, when I ask, "Shouldn't the compiler be able to notice that a variable isn't changed in it's lifetime?" Most of the const values are just local and never leave the function but the weenies continue to stomp their feet when I use "var". The compilers are smart. Let them do their thing.

> Shouldn't the compiler be able to notice that a variable isn't changed in it's lifetime?

The compiler can, I can't (efficiently). const spam also occasionally catches when I modify the wrong variable.

Re: Why Const Doesn't Make C Code Faster

#85

Earlier quoted context omitted.

Does it enforce these attributes or are they just a promise by the code author?

D has a `pure` attribute for functions, and yes it is enforced. It's enforced even to the point where it becomes a PITA, but when you manage to make functions pure, you know it's solid. One pain point with pure functions is you can't insert debug logging statements. D has a special case for that - purity for a statement isn't checked if it is prefixed with the `debug` keyword: pure int square(int x) { debug printf("c…

This means you can't re-order the computation, though, or memoize it—at least not the the extent it's possible without IO.

Re: Why Const Doesn't Make C Code Faster

#86

Earlier quoted context omitted.

Does it enforce these attributes or are they just a promise by the code author?

D has a `pure` attribute for functions, and yes it is enforced. It's enforced even to the point where it becomes a PITA, but when you manage to make functions pure, you know it's solid. One pain point with pure functions is you can't insert debug logging statements. D has a special case for that - purity for a statement isn't checked if it is prefixed with the `debug` keyword: pure int square(int x) { debug printf("c…

I wonder does that mean you could also enforce freeing memory allocated by a pure function as well?

Re: Why Const Doesn't Make C Code Faster

#87
post #62

Const won't necessarily make things faster but constant values will (whether or not explicitly inferred). I noticed, for example, a 2x+ speedup in one of my ray tracers by downgrading my dynamic 2d/3d/4d vector class* to always have a constant size of 3. * (poor choice, I know)

That has nothing to do with const. Your dynamic vectors are allocating memory over and over on the heap, which is expensive. When you use a constant size they can be allocated on the stack, which is cheap.

Good guess, but in this case the size of the vector container was always constant - 4 elements (even if only 2 or 3 of them were ever used). Presumably what made it faster was being able to unroll loops? (only a guess, never looked at the disassembly) -- so instead of 0 to x on each vector element, it would loop through 0 to 2 and could optimize around this for each function.

Re: Why Const Doesn't Make C Code Faster

#88

I think the big problem here is that const doesn't really truly say anything about aliasing. Even excluding casting evils, calling a method with a const pointer only means that the method isn't supposed to change the value. It does not mean that the caller isn't going to change things (particularly from another thread). The languages are simply too permissible when it comes to what a pointer means and how it can be u…

Even excluding casting evils, calling a method with a const pointer only means that the method isn't supposed to change the value. It does not mean that the caller isn't going to change things (particularly from another thread).

This is incorrect.

Actually, you promise not to change things from another thread, DMA, interrupt handler, signal, etc, with any non-volatile reference passed, let alone a const! The compiler loads things into registers and has no way to know if memory in a passed reference changes underneath the hood-- it freely generates code that assumes that the things it has pointers do, do not change. It can freely make optimizations that lead to incorrect computation, infinite loops, segmentation faults if this is not obeyed. If you've ever head about how "double check locking" is an antipattern, this is a big part of why.

e.g. from ISO 9899:

Alternatively, an implementation might perform various optimizations within each translation unit, such that the actual semantics would agree with the abstract semantics only when making function calls across translation unit boundaries. In such an implementation, at the time of each function entry and function return where the calling function and the called function are in different translation units, the values of all externally linked objects and of all objects accessible via pointers therein would agree with the abstract semantics. Furthermore, at the time of each such function entry the values of the parameters of the called function and of all objects accessible via pointers therein would agree with the abstract semantics. In this type of implementation, objects referred to by interrupt service routines activated by the signal function would require explicit specification of volatile storage, as well as other implementation-defined restrictions.

This is the model used by pretty much every C compiler you'll encounter. When you e.g. acquire a lock, you call something in a different linkage unit so multithreaded stuff behaves properly.

For const, the guarantees go further: you promise it won't change elsewhere (relevant standards text quoted in my other comment).

Re: Why Const Doesn't Make C Code Faster

#89

Const does make C go faster, just not in most of the places you see it used. For const to help, the object itself needs to be defined const. Just taking a `const object * ` (or `const object&` in C++) doesn't help you determine the constness of the underlying object, and that usually accounts for the majority of const usage by volume. Limiting the scope to of actual const definitions , it can help a lot, but only in…

BINGO!!! The pointer is constant, not the item being pointed to. Since you’re dereferencing the pointer, i.e. accessing the non-const bits, the compiler must reload.

Re: Why Const Doesn't Make C Code Faster

#90
post #86

Earlier quoted context omitted.

D has a `pure` attribute for functions, and yes it is enforced. It's enforced even to the point where it becomes a PITA, but when you manage to make functions pure, you know it's solid. One pain point with pure functions is you can't insert debug logging statements. D has a special case for that - purity for a statement isn't checked if it is prefixed with the `debug` keyword: pure int square(int x) { debug printf("c…

I wonder does that mean you could also enforce freeing memory allocated by a pure function as well?

I'm not sure what you mean?

Allocators are often pure in D, they probably shouldn't be but that would mean allocating outside the function which would be ugly and probably buggy too

Post reply on HN