TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Why Const Doesn't Make C Code Faster

291 点作者 mnem超过 5 年前

37 条评论

WalterBright超过 5 年前
&gt; This is true in practice because enough real-world C code has “I know what I’m doing” casting away of const.<p>I found this out the hard way when I implemented OptimumC, the first data flow analysis optimizer for DOS C compilers back in the 1980&#x27;s.<p>I had to undo doing optimizations on const.<p>Anecdote: Optimum C blew away all the other C compilers on a magazine benchmark article because it figured out that the benchmark code did nothing and deleted it. The author didn&#x27;t ask me about it, he just assumed the compiler was buggy and gave us a bad review. Sigh.<p>When other compilers did DFA, the benchmarks got changed.
评论 #20743680 未加载
评论 #20742293 未加载
评论 #20743401 未加载
评论 #20745215 未加载
评论 #20742183 未加载
评论 #20742114 未加载
ljackman超过 5 年前
The key difference between `const` and the `register` and `inline` keywords is that, despite all of them often flagging optimisations that the compiler can often work out anyway, `const` still aids human comprehension by declaring constraints, whereas the latter two do not.<p>It seems that interprocedure optimisations in modern compilers make a lot of const-by-reference optimisations apply even when the code is mutable-by-reference in the parameter list but the function body doesn&#x27;t modify it in practice. This would only work if it could deterministically work out which function is called.<p>Local constant stack values surely can be completely deterministically verified as such by the optimiser even without the `const` modifier. They could be overwritten without a C assignment to it, via the stack from a buffer overflow of an array next to it, but that&#x27;s undefined behaviour so a compiler is presumably free to assume it is not modified, eliminate unnecessary register&#x2F;memory loading code, and let the developers deal with the consequences.<p>As trailing `const` on member functions outlaws modifications via `this`, it would follow that the same optimisation-even-without-modifier process would apply as to `const` local stack values.<p>As constancy is a constraint that aids human comprehension, there&#x27;s a good reason for choosing a keyword just as short as the mutable equivalent, such as Swift&#x27;s `let` vs `var`; if the more constrained equivalent is equally or more convenient, more constrained and thus easy-to-reason-about code becomes more common.
评论 #20743205 未加载
评论 #20743136 未加载
dmitrygr超过 5 年前
gcc has some attributes to help with that, for example try __attribute__((pure)) on funcs that will always return the same thing for the same inputs (given the same global state) and do not modify said input or state (and thus can be called more or fewer times than programmer wrote). Usually gcc will be quite aggressive with optimizations if you use that.<p>For even more aggressiveness, try __attribute__((const)) which tells it that the func accesses NOTHING but the params, not even global vars. Of course this is quite limiting. You can also use this as a trick when <i>YOU</i> know that the only accessed global state is itself constant but gcc does not know that. This can produce substantial savings in number of calls of funcs that, for example, do lookups in large constant data tables, like table-based versions of sin() and cos().<p>In the example the article gives, adding __attribute__((pure)) to constFunc() does produce the behaviour author wanted and then some<p>LWN has more: <a href="https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;285332&#x2F;" rel="nofollow">https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;285332&#x2F;</a>
评论 #20741863 未加载
评论 #20745009 未加载
评论 #20743141 未加载
BeeOnRope超过 5 年前
Const does make C go faster, just not in most of the places you see it used.<p>For const to help, the <i>object itself</i> needs to be <i>defined</i> const. Just taking a `const object <i></i>* ` (or `const object&amp;` in C++) doesn&#x27;t help you determine the constness of the underlying object, and that usually accounts for the majority of const usage by volume.<p>Limiting the scope to of actual const <i>definitions</i>, it can help a lot, but only in cases where the compiler couldn&#x27;t move that anyways. So local variable const definitions rarely help, because the compiler can often already prove they are const by inspection (but they can help if the variable escapes).<p>They are useful especially for global variables (and moral equivalents, like static class members in C++), since the compiler cannot prove by examining only the current TU whether the variable is unmodified (and it is a hard problem even if the whole program can be inspected), so const is a useful promise there.
评论 #20742779 未加载
mrpippy超过 5 年前
On some microcontrollers, marking variables&#x2F;arrays as const allows the compiler to access them directly from flash rather than having to copy them into RAM at startup. I used this to great effect on a PIC24 with 256KB flash&#x2F;16KB RAM.
评论 #20742536 未加载
评论 #20742199 未加载
mlyle超过 5 年前
This assumes that the compiler can actually infer that a const-by-reference isn&#x27;t modified.<p>The second we have indirection (function pointers), or a different source file without whole-program-optimization, or a library, these assumptions break down.<p>Further, the author assumes that the compiler can&#x27;t benefit from the knowledge that something is const because the const can be cached away. This isn&#x27;t true, e.g. per ISO9899 6.7.3.5:<p><i>If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined. If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.</i>
klingonopera超过 5 年前
I hardly ever bother optimizing my code anymore, with -O3 nothing I do ever really seems to make a difference.<p>The real reason to use &quot;const&quot; is to show intent.<p>See &quot;Const and Rigid Parameters&quot; in this wonderful article about the Doom 3 source code: <a href="https:&#x2F;&#x2F;kotaku.com&#x2F;the-exceptional-beauty-of-doom-3s-source-code-5975610" rel="nofollow">https:&#x2F;&#x2F;kotaku.com&#x2F;the-exceptional-beauty-of-doom-3s-source-...</a>
评论 #20741912 未加载
评论 #20747976 未加载
ridiculous_fish超过 5 年前
const_cast risk is not why the compiler emits a reload. Indeed we don&#x27;t even need to pass x to constFunc to get the reload: see line 7 in <a href="https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;TjmWxL" rel="nofollow">https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;TjmWxL</a><p>Consider that `x` may point to a global variable which `something` may modify. That is why the reload is necessary.<p>edit: I just realized that the reload would be necessary even without an intervening function call. <a href="https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;QhVzlV" rel="nofollow">https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;QhVzlV</a><p>Consider that `x` may point to errno; then printf would modify it!
评论 #20744365 未加载
评论 #20743671 未加载
cogman10超过 5 年前
I think the big problem here is that const doesn&#x27;t really truly say anything about aliasing.<p>Even excluding casting evils, calling a method with a const pointer only means that the method isn&#x27;t supposed to change the value. It does not mean that the caller isn&#x27;t going to change things (particularly from another thread).<p>The languages are simply too permissible when it comes to what a pointer means and how it can be used.<p>For const to be optimizable, you&#x27;d need to take Rust&#x27;s approach and make language level guarantees that &quot;You can&#x27;t do bad things with this&quot;. C and C++ missed that boat.
评论 #20742775 未加载
WalterBright超过 5 年前
This issue is why D has both const and immutable qualifiers. const can&#x27;t be optimized because there may be other mutable references to the same memory object. But for immutable references, there cannot be.<p>It is possible to cast away const and immutable in D, but these are only allowed in system code, presumably where the programmer actually does know what he&#x27;s doing.
pcwalton超过 5 年前
The most succinct way I&#x27;ve heard this explained is: &quot;Const means &#x27;<i>I</i> won&#x27;t mutate this&#x27;. It doesn&#x27;t mean &#x27;<i>nobody</i> will mutate this&#x27;.&quot;<p>To do optimizations, compilers really need to know that <i>nobody</i> will mutate a value; just knowing that a particular function won&#x27;t mutate a value isn&#x27;t that helpful.
评论 #20743444 未加载
not2b超过 5 年前
Unfortunately in C++, the compiler is not allowed to assume that if it passes a const reference to a function, that function will not change the object. The function is allowed to cast away const and modify the object. I&#x27;m not happy that they did it that way; I would have preferred it if cast-away-const were more restricted (for example, allowed when calling a child function that takes a char* but doesn&#x27;t modify the pointed-to C string), with the idea being that if a function has only a pointer to const or a reference for a const object, it has read permission on the object and lacks write permission. But that isn&#x27;t how the language works.
评论 #20741699 未加载
评论 #20742560 未加载
评论 #20741958 未加载
评论 #20742152 未加载
评论 #20742226 未加载
Ididntdothis超过 5 年前
I have done a lot of profiling work and I have observed similar things. One thing is const, another is virtual functions. A lot of people think they add overhead and avoid them for performance reasons but my profiling almost never showed them as a problem. Same for const and inline. it’s really hard to predict what the optimizer will do.<p>Obviously there are stupid things that can be avoided from the start but in general I prefer clean code where people write for readability and simplicity and not speed.
评论 #20741640 未加载
评论 #20741600 未加载
QuadrupleA超过 5 年前
I used to strive for &quot;const correctness&quot; in my game engine code, and wasted a fair amount of time fighting the compiler and editing function signatures as requirements changed. Mostly eliminating const from the codebase simplified things a lot.<p>Didn&#x27;t do any comparison studies of performance, but the productivity boost from not having to think about it was nice, and I suspect any performance difference is margin-of-error stuff like the sqlite results in this article.
评论 #20766956 未加载
mcv超过 5 年前
Not quite the same issue, but this reminds me of my very first job, back in 2001, where we used a homebrew C++ framework that separated lots of concerns, and then used a single massive .h file with 10,000 const uints to tie everything together.<p>Compiling took over 2 hours. The header was generated automatically, but after I added a macro that replaced those const uints with #defines, compile time dropped to 30 minutes, which was quickly voted the biggest productivity enhancement in that project.<p>More relevant to the topic, in javascript programming I recently switched to using const instead of let wherever possible. Most variables don&#x27;t actually vary, so let&#x27;s make that explicit. That can prevent some unexpected surprises (though not all, as objects and arrays in constants are not immutable).
chmaynard超过 5 年前
Many laws exist that express the intent of a law-making body but are either unenforceable or too expensive to enforce in any meaningful way. Perhaps the const declaration in C is an example of this type of law.<p>In contrast, a Standard ML compiler can enforce this law because the language itself insists that all bindings are immutable.
jasonzemos超过 5 年前
I wish there was a C++ compiler flag which made everything const by default and required the mutable keyword otherwise. This is obviously non-standard and would break included headers, but alternatively a #pragma could scope that option for project code coming after non-project includes.
kazinator超过 5 年前
Well, of course:<p><pre><code> void constByArg(const int *x) { printf(&quot;%d\n&quot;, *x); constFunc(x); printf(&quot;%d\n&quot;, *x); } </code></pre> Here, the object referenced by pointer <i>x</i> is non-local, and so is <i>constFunc</i>.<p>The object could be modified in legal ways nothing to do with <i>constFunc</i> stripping away the qualifier.<p>Also, if the object is not <i>defined</i> const, then <i>constFunc</i> is allowed to do that, too.<p>Then the next, correct, example with a const protected local shows that two instructions are shaved off. That&#x27;s a wortwhile saving that could be leveraged to get faster code.<p>If you&#x27;re passing local variables into helper functions which are not supposed to change them, you can shave off some cycles with const.<p>&gt; <i>I mean, I removed const from the entire program</i><p>Maybe sqLite doesn&#x27;t use <i>const</i> specifically with a view toward optimization. To see an overall performance impact, there would have to be some case in a &quot;hot spot&quot; of the program, where <i>const</i> is used with some local variables being passed into functions. (Or whatever other case we can ferret out where <i>const</i> happens to help.)<p>There are some widely applicable optimizations which scoop up all the &quot;low hanging fruit&quot; improvements, but after that, optimization is a game of eking out small gains with specialized cases.
ndesaulniers超过 5 年前
If clang can see the definition of `constFunc` and deduce that its parameters are `noescape`, then I think it can avoid reloading `x`.<p>A recent optimization in clang (not sure if it&#x27;s in clang-9 or clang-10) will remove memsets to variables declared const, which usually come from assigning through a pointer that&#x27;s had const (of the pointed to type) casted away. The MIPS Linux kernel won&#x27;t boot when built with clang due to the above (I sent a patch 2 weeks ago)
foxhill超过 5 年前
overlooks the value of const qualification for the caller - if the argument is marked as const, the caller might reasonably assume the data won’t be changed.
评论 #20741611 未加载
评论 #20741538 未加载
评论 #20741535 未加载
sclangdon超过 5 年前
C++, rather than C, but there was a GOTW post about this years ago, which explains the situation in detail.<p><a href="http:&#x2F;&#x2F;www.gotw.ca&#x2F;gotw&#x2F;081.htm" rel="nofollow">http:&#x2F;&#x2F;www.gotw.ca&#x2F;gotw&#x2F;081.htm</a>
caf超过 5 年前
It&#x27;s true that, as demonstrated, const-qualifying your pointer arguments is very unlikely to allow any optimisations on its own.<p>However, const-qualifying your pointer arguments where the pointed-to object isn&#x27;t changed is what allows you to make more liberal use of const-qualified <i>declarations</i>, and as also demonstrated by the article, those in turn do allow some optimisations.<p>Additionally, there is some safety on the table: if your C program makes use of pointers to structures full of function pointers to implement polymorphism, making those pointers const-qualified allows your underlying structures full of function pointers to be declared const, which in turn allows them to be stored in hardware-enforced read-only memory.<p>As a side note, I&#x27;ve often thought that block-scope variables declared const and whose address is never taken should be automatically made static.
Someone超过 5 年前
<p><pre><code> &#x2F;&#x2F; x is just a read-only pointer to something that may or may not be a constant void constFunc(const int *x) </code></pre> Is that correct? I read that as “x is a pointer to a const int”<p>If you want “x is a read-only pointer to an int”, you would need<p><pre><code> void constFunc(int * const x) </code></pre> The article also doesn’t mention the case “x is a read-only pointer to a constant int”. To state that, you would use<p><pre><code> void constFunc(const int * const x) </code></pre> (<a href="https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;1143272" rel="nofollow">https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;1143272</a>)
评论 #20742601 未加载
rurban超过 5 年前
Overly broad statement. const for global or static variables do make code faster, as they are placed in the .rodata segment, which allows swapping them out for free. This can be a huge win.<p>He only talks about const args, where the compiler does not try yet to check for casts which violate the constness guarantees. (DFA, Escape Analysis). And thus misses all important optimizations. You cannot rely on that never being implemented in the future. With LTO they already do I think.
fallingfrog超过 5 年前
I use const all over the place, but no so much to make the code faster as to eliminate potential stupid mistakes.
gavanwoolery超过 5 年前
Const won&#x27;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&#x2F;3d&#x2F;4d vector class* to always have a constant size of 3.<p>* (poor choice, I know)
评论 #20742206 未加载
评论 #20742229 未加载
评论 #20742241 未加载
tutfbhuf超过 5 年前
You should also test it with older compiler versions from the 80s&#x2F;90s. There are some falsehood believes about programming now that were true some decades ago. I&#x27;m not saying that this is the case here, but it&#x27;s worth to keep that in mind.
numlock86超过 5 年前
I just see too many programmers that right from the start try to micro-optimize their code with things like this. You&#x27;ll usually see very well written code but with all sorts of hacks, taken from blogs and StackOverflow answers and whatnot all across the web, but in the end they fail to optimize their actual algorithm and end up with some ultra-high memory footprints or O(n^3) stuff instead of some nice O(log(n)) for example. And they&#x27;ll argue that they already &quot;optimized the sh*t out of it&quot;, because they saved a couple of hundred assembly calls in a binary file around the size of a few megabytes ...
SomaticPirate超过 5 年前
Is the same true for other compiled languages? Like Golang?
评论 #20742658 未加载
评论 #20741679 未加载
haberman超过 5 年前
&gt; So, what’s const for? For all its flaws, C&#x2F;C++ const is still useful for type safety.<p>Const variables can also be mapped read-only. This gives you hardware protection against modifications, and also uses less RAM if the const variable is in a shared library (multiple processes can share the same mappings).
3xblah超过 5 年前
Surprised no one has mentioned what the author of C, Dennis Ritchie, said about the addition of &quot;const&quot; to the language.<p><a href="https:&#x2F;&#x2F;www.lysator.liu.se&#x2F;c&#x2F;dmr-on-noalias.html" rel="nofollow">https:&#x2F;&#x2F;www.lysator.liu.se&#x2F;c&#x2F;dmr-on-noalias.html</a>
评论 #20743262 未加载
craftoman超过 5 年前
We&#x27;re talking about billions of calls that have milliseconds in difference. That&#x27;s irrelevant when building a basic app that sits on a 10K worth of hardware machine with hundreds of CPUs.
kmadento超过 5 年前
Shouldn&#x27;t the test instead be: const int * const &lt;variable name&gt;<p>Haven&#x27;t profiled it but would make more sense to have the pointer also be const instead of having a non const pointer as input?
评论 #20742312 未加载
badsectoracula超过 5 年前
&gt; So most of the time the compiler sees const, it has to assume that someone, somewhere could cast it away, which means the compiler can’t use it for optimisation. This is true in practice because enough real-world C code has “I know what I’m doing” casting away of const.<p>Some years ago i&#x27;d agree, but experience has shown that C&#x2F;C++ compiler writers would rather win benchmark games than keep working code working. So it&#x27;d be nice if there was a better reason than &quot;well, a lot of code would break if they did that&quot;.
评论 #20741777 未加载
评论 #20742398 未加载
评论 #20741738 未加载
ma2rten超过 5 年前
It seems to me that compilers could benefit from doing analysis of functions and providing that information to callers.
评论 #20745485 未加载
known超过 5 年前
Extra protection of data costs speed;
stephc_int13超过 5 年前
I once had a very stubborn intern who decided to add as much const as he could in our codebase. What followed was a heated discussion and I did a global replace of const by nothing.<p>The main problem with const is that it&#x27;s ugly, it&#x27;s viral and it does not add any value to the code.<p>And I know all the supposedly good things about this, but I never found any real usage in practice.
评论 #20743157 未加载