6 ms·
Some of the "performance penalties" look like FUD to me. At least to the extent implied in the article. For example "use of an unitialized variable". Given tha
by bhaak 12y ago
Some of the "performance penalties" look like FUD to me. At least to the extent implied in the article.
For example "use of an unitialized variable". Given that the compiler already has to analyze the program flow to determine if the variable could be use unitialized to output that warning, the optimization step to not initialize those variables that are written to before used doesn't seem so far away. This happens at compile time.
But, there's also the fact that a modern OS gives you heap memory zeroed mostly for free. A call to calloc is highly optimized nowadays. It needs to be for security reasons, as a program must never receive memory with data left from a different process.
Likewise the signed integer overflow check. Modern CPUs are so superscalar internally that an overflow check (which doesn't get flagged most of the time anyway) doesn't add anything to the execution speed.
And finally we are able to use that without resorting to assembler. GCC 5 has added support for built-in functions for arithmetics with overflow checking.
- haberman 12y ago> But, there's also the fact that a modern OS gives you heap memory zeroed mostly for free. A call to calloc is highly optimized nowadays. It needs to be for security reasons, as a program must never receive memory with data left from a different process. Memory often is coming from previously-freed heap space within the process. There is no security need to zero such memory. Zeroing it wouldn't even help, because the process is free to read the memory before malloc returns it. And calloc, no matter how optimized it is, will still be more expensive than malloc which doesn't have to zero the memory. > Modern CPUs are so superscalar internally that an overflow check (which doesn't get flagged most of the time anyway) doesn't add anything to the execution speed. "Doesn't add anything" is not correct. These checks are not free: http://danluu.com/integer-overflow/ http://danluu.com/integer-overflow/ https://news.ycombinator.com/item?id=8765714#up_8765979 https://news.ycombinator.com/item?id=8765714#up_8765979
- barrkel 12y agoZeroed memory should not be particularly expensive on modern machines, because we have a lot of parallelism available to zero it off working threads. There might be some constraint on memory bandwidth, but IMO memory latency is a bigger issue, usually preventing maximizing memory throughput, so there should be some spare. The danluu link doesn't really support your argument. Yes, the checks aren't free, but they aren't very costly either in practice, and much of the cost is down to C compilers not being optimized for generating range-checking code. I feel you're also possibly missing a longer term feedback loop issue. When software starts relying on things like overflow checks and zeroed memory, hardware manufacturers like Intel start building and optimizing hardware to make them faster. The "prefer performance over correctness" bias that's existed in the C world has been responsible for a lot of damage. We need to get out of it.
- Narishma 12y agoZeroing memory is certainly not free, and if you're doing some types of real-time applications, can have a significant cost. http://randomascii.wordpress.com/2014/12/10/hidden-costs-of-memory-allocation/ http://randomascii.wordpress.com/2014/12/10/hidden-costs-of-...
- pkolaczk 12y agoIf the compiler could prove you never read an array element before writing (like it is most of the time in Java, and should be all of the time in C), it could optimize the entire zeroing step away. Java does this very often. And initializing your variables close to the point of declaring them is a good practice in C anyways, which should make it easy for the compiler to analyze.
- ArkyBeagle 12y agoBut if zeroing memory is necessary for the program to be correct, hang the cost. I don't know what sort of "real time applications" would require gambling on the initial state of memory. If you really can't afford to use dynamic memory, don't. 'C' will cheerfully allow you to hog as much as you want outside the heap.
- shadowfox 12y ago> But if zeroing memory is necessary for the program to be correct, hang the cost. Sure. And your application should bear that cost and not necessarily every application written in C. Maybe there is a case for using a safer malloc implementation for your program? > I don't know what sort of "real time applications" would require gambling on the initial state of memory. This isn't really gambling. If you know you are going to initialize the memory with sane values immediately (and this is a common practice), it is a waste to do that initial zeroing.
- ArkyBeagle 12y agoAh - in that case, I'd agree. I couldn't draw to that conclusion from the text provided - that's just as good as zeroing ( and, as you say ) renders the zeroing moot.
- bhaak 12y ago>> Modern CPUs are so superscalar internally that an overflow check (which doesn't get flagged most of the time anyway) doesn't add anything to the execution speed. > "Doesn't add anything" is not correct. These checks are not free: This statement was in regard to what happens inside the CPU. What happens on the level of the individual compilers is still a problem as we only see about now that the compilers are starting to optimize those cases. In that regard we don't know yet the true costs of those checks but time will tell.
- haberman 12y ago> This statement was in regard to what happens inside the CPU. In that regard, the statement is still incorrect. The link I posted above analyzes the cost at the CPU level given the optimal machine code. It estimates an upper bound of a 2x overhead per overflow-checked add. ie. not free.
- xamuel 12y ago>the optimization step to not initialize those variables that are written to before used doesn't seem so far away Determining whether or not variables will be used uninitialized is equivalent to solving the halting problem.
- pkolaczk 12y agoIn general case only. For most of typical code, it is quite obvious. If your program makes initialization depend on many conditions which makes it hard to analyze for the compiler, you're probably writing very fragile code that will soon bite you with UB.
- haberman 12y ago> For most of typical code, it is quite obvious. [citation needed] > If your program makes initialization depend on many conditions which makes it hard to analyze for the compiler, you're probably writing very fragile code that will soon bite you with UB. Say you allocate a stack, and access it with the following pattern: bool push(stack *st) { if (st->top == st->limit) return false; st->top++; st->top->foo = FOO_INIT; st->top->bar = BAR_INIT; return true; } void pop(stack *st) { assert(st->top != st->stack); st->top--; } void stack_alloc(stack *st, int n) { st->stack = malloc(n * sizeof(*st->stack)); st->top = st->stack; st->limit = st->stack + n - 1; } If you only access the stack through st->top, it is easy to see (for a human) that the stack will never be accessed uninitialized. Good luck getting the compiler to build an inductive proof of that though. This is just the first example that popped into my mind because I was doing this yesterday.
- pkolaczk 12y agoI said most, not every. int x; .... x = 5; printf("%d\n", x); Anyway, in you code the cost of malloc is a lot higher than the cost of zeroing out. And I guess most of the time it is hard to elide variable initialization would be in places where you have non-local variable use and you do heap allocation.