Hacker News new | ask | show | jobs
by fbbbbb 3831 days ago
So what do you do when an index into an array is out of bounds at run-time. You can't perform a check every time because that would go against the C's principle, and at the same time it would degrade performance, making it less useful compared to newer languages.

How would you implement defined behavior without a significant (which is what an if check is at that level) overhead in this case?

2 comments

> So what do you do when an index into an array is out of bounds at run-time. You can't perform a check every time because that would go against the C's principle, and at the same time it would degrade performance, making it less useful compared to newer languages.

Bounds checks are not really a problem if you get rid of for loops in favor of constructions that eliminate bounds checks by construction (e.g. iterators). Of course, they're still problems in languages that continue the tradition of C-style for loops.

This is a classic example of how just defining away undefined behavior can make C unacceptably slow, but does not necessarily make other languages unacceptably slow.

Compared to the economic cost of bugs, bound checks everywhere are (very very) cheap. Even more so with the CPU and compilers we have today, which are more than sufficiently smart from the point of view of when C was created. Intel is even adding some new instructions in their CPU to make that even less costly than you could imagine in even some crazy C based situation you would not think to be possible in the first place, because of C. But the cost here is extra complexity, for something that should have been built-in in the first place.

More technically to address fears of slowdowns even with simpler architectures, the additional checks will likely be factored most of the time (for example before a loop with linear accesses). When they are not, to have a real impact 1/ it has to be in a really hot code path (like 1% or maybe even 0.1% or even less of a real system) 2/ the cpu should not be able to use empty OOO slots and execution units to execute it without any extra penality 3/ this is quite a deduction from the two preceding points, but if we are talking about a big array being accessed in random order this will be slow because of RAM access anyway, an extra check won't induce any meaningful slowdown maybe even if it were mispredicted (which it will not be - in regard to performance).

Like always if you have any performance issue, first profile. And actually I can't remember having ever heard a single person complaining that some bound checking in a program was the cause of their slowdowns. It often far more macroscopic, and easy to fix anyway when it is that much micro. Considering usual modern systems, they are sometimes so slow that the problem is certainly NOT native bound checking, but very probably architectural madness.

If you were frequently catching out of bounds accesses your CPU's branch predictor would be making mistakes and you'd be frequently eating the branch mispredict penalty. Any extra instruction or check that alters the control flow is often much more expensive than just another addition. However, in this case if you're taking the branch something is seriously broken so that you should not be facing this. Pre-Haswell Intel CPUs only had one branch slot so you still might have a penalty but as you say this isn't the end of the world.