3 ms·
Back when I was writing real-time signal processing code, I spent quite a bit of time refactoring code from variations of styles A and B to style C. The proble
by vonmoltke 12y ago
Back when I was writing real-time signal processing code, I spent quite a bit of time refactoring code from variations of styles A and B to style C. The problem Carmack talks about is even worse when some of those subroutines were in separate source files. Over the course of my refactorings, I was able to re-arrange and combine functionality in ways that were not possible with the discrete functions. I was able to pull operations out of inner loops that repeatedly and expensively calculated the same values. I found and fixed all sorts of actual or potential bugs in doing this. The original code was extra hairy, though, because it was written for DSPs, not general-purpose microprocessors.
As a side note, the original code contained large numbers of manual loop unrolling optimizations like noted in the email. I actually saw a performance increase from removing them. Same in some cases for manually inlining the function calls. From what I could tell, writing simpler, inline code made the optimizer much more efficient.
- AdmiralAsshat 12y agoWouldn't in-lining make unit testing more difficult? Admittedly I am not a very experienced programmer, but I thought the general line of thought with regards to making your program easier to test would be that each function should do as little as possible.
- clarry 12y agoYes it would, but Carmack is advocating the inlining of functions that deal with game state. These tend to be kinda hard to test in isolation anyway. But he does also advocate keeping small helper functions pure.
- lutusp 12y ago> Wouldn't in-lining make unit testing more difficult? That depends on the nature of the inline code. If it simply unrolls a local loop that has no side effects, then it's structurally identical to the original loop, but (in some cases) faster. This is demonstrated by the fact that some compilers can be coerced to inline certain repetitive actions originally written in the form of loops, as a speed optimization.
- vonmoltke 12y agoThe algorithms we were implementing were very hard to test using conventional unit test techniques. The only way to properly test this code was to run the full system with recorded input data. We used data extractions at key points in the pipeline to verify that the code was working correctly. With a series of extractions it was possible to figure out where the problem was, and with an understanding of the algorithms it was possible to figure out what it was. The extractions themselves could be placed at arbitrary locations.
- dognotdog 12y agoThat "premature optimization is the root of all evil" is now a fairly uncontroversial statement, but people don't realize that this insight not only applies to performance. The OO/functional/whatever-current-fashion movement almost universally starts cargo-culting with the main principles, no longer thinking about why this or that is done. To come back to the point at hand, regularly writing all kinds of code, from embedded to desktop to mobile, I can only nod vigorously at Carmack's observations Always writing minimal functions doesn't work 100% of the time, but is unfortunately often enforced vehemently in large teams, as the ones in charge don't trust the rest to be sensible. There should always be a good reason to follow this or that rule, but when the rules of the team are broken intenionally, it'd better be documented to avoid confusion later on!