<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>#AltDevBlogADay &#187; John-Carmack</title>
	<atom:link href="http://www.altdevblogaday.com/author/john-carmack/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.altdevblogaday.com</link>
	<description>Each day a little more #gamedev love</description>
	<lastBuildDate>Thu, 17 May 2012 03:06:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Functional Programming in C++</title>
		<link>http://www.altdevblogaday.com/2012/04/26/functional-programming-in-c/</link>
		<comments>http://www.altdevblogaday.com/2012/04/26/functional-programming-in-c/#comments</comments>
		<pubDate>Thu, 26 Apr 2012 22:13:37 +0000</pubDate>
		<dc:creator>John-Carmack</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.altdevblogaday.com/?p=25786</guid>
		<description><![CDATA[<p class="MsoNormal">Probably everyone reading this has heard “functional programming” put forth as something that is supposed to bring benefits to software development, or even heard it touted as a silver bullet.  However, a trip to <a href="http://en.wikipedia.org/wiki/Functional_programming">Wikipedia</a> for some more information can be initially off-putting, with early references to <a href="http://en.wikipedia.org/wiki/Lambda_calculus">lambda calculus</a> and <a href="http://en.wikipedia.org/wiki/Formal_system">formal systems</a>.  It isn’t immediately clear what that has to do with writing better software.</p>
<p><a href="http://www.altdevblogaday.com/2012/04/26/functional-programming-in-c/" class="more-link">Read more on Functional Programming in C++&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p class="MsoNormal">Probably everyone reading this has heard “functional programming” put forth as something that is supposed to bring benefits to software development, or even heard it touted as a silver bullet.  However, a trip to <a href="http://en.wikipedia.org/wiki/Functional_programming">Wikipedia</a> for some more information can be initially off-putting, with early references to <a href="http://en.wikipedia.org/wiki/Lambda_calculus">lambda calculus</a> and <a href="http://en.wikipedia.org/wiki/Formal_system">formal systems</a>.  It isn’t immediately clear what that has to do with writing better software.</p>
<p class="MsoNormal">My pragmatic summary:  A large fraction of the flaws in software development are due to programmers not fully understanding all the possible states their code may execute in.  In a multithreaded environment, the lack of understanding and the resulting problems are greatly amplified, almost to the point of panic if you are paying attention.  Programming in a functional style makes the state presented to your code explicit, which makes it much easier to reason about, and, in a completely pure system, makes thread race conditions impossible.</p>
<p class="MsoNormal">I do believe that there is real value in pursuing functional programming, but it would be irresponsible to exhort everyone to abandon their C++ compilers and start coding in <a href="http://en.wikipedia.org/wiki/Lisp_%28programming_language%29">Lisp</a>, <a href="http://en.wikipedia.org/wiki/Haskell_%28programming_language%29">Haskell</a>, or, to be blunt, any other fringe language.  To the eternal chagrin of language designers, there are plenty of externalities that can overwhelm the benefits of a language, and game development has more than most fields.  We have cross platform issues, proprietary tool chains, certification gates, licensed technologies, and stringent performance requirements on top of the issues with legacy codebases and workforce availability that everyone faces.</p>
<p class="MsoNormal">If you are in circumstances where you can undertake significant development work in a non-mainstream language, I’ll cheer you on, but be prepared to take some hits in the name of progress.  For everyone else: <em><strong>No matter what language you work in,</strong> <strong>programming in a functional style provides benefits.  You should do it whenever it is convenient, and you should think hard about the decision when it isn’t convenient</strong>.</em>  You can learn about lambdas, monads, currying, composing lazily evaluated functions on infinite sets, and all the other aspects of explicitly functionally oriented languages later if you choose.</p>
<p class="MsoNormal">C++ doesn’t encourage functional programming, but it doesn’t prevent you from doing it, and you retain the power to drop down and apply SIMD intrinsics to hand laid out data backed by memory mapped files, or whatever other nitty-gritty goodness you find the need for.</p>
<p>&nbsp;</p>
<p class="MsoNormal"><span style="font-size: 18pt">Pure Functions</span></p>
<p class="MsoNormal">A pure function only looks at the parameters passed in to it, and all it does is return one or more computed values based on the parameters.  It has no logical <em>side effects.  </em>This is an abstraction of course; every function has side effects at the CPU level, and most at the heap level, but the abstraction is still valuable.</p>
<p class="MsoNormal">It doesn’t look at or update global state.  it doesn’t maintain internal state.  It doesn’t perform any IO.  it doesn’t mutate any of the input parameters.  Ideally, it isn’t passed any extraneous data – getting an <span style="font-family: 'Courier New'">allMyGlobals</span> pointer passed in defeats much of the purpose.</p>
<p class="MsoNormal">Pure functions have a lot of nice properties.</p>
<p class="MsoNormal">Thread safety.  A pure function with value parameters is completely thread safe.  With reference or pointer parameters, even if they are const, you do need to be aware of the danger that another thread doing non-pure operations might mutate or free the data, but it is still one of the most powerful tools for writing safe multithreaded code.</p>
<p class="MsoNormal">You can trivially switch them out for <a href="http://altdevblogaday.com/2011/11/22/parallel-implementations">parallel implementations</a>, or run multiple implementations to compare the results.  This makes it much safer to experiment and evolve.</p>
<p class="MsoNormal">Reusability.  It is much easier to transplant a pure function to a new environment.  You still need to deal with type definitions and any called pure functions, but there is no snowball effect.  How many times have you known there was some code that does what you need in another system, but extricating it from all of its environmental assumptions was more work than just writing it over?</p>
<p class="MsoNormal">Testability.  A pure function has <em>referential transparency</em>, which means that it will always give the same result for a set of parameters no matter when it is called, which makes it much easier to exercise than something interwoven with other systems.   I have never been very responsible about writing test code;  a lot of code interacts with enough systems that it can require elaborate harnesses to exercise, and I could often convince myself (probably incorrectly) that it wasn’t worth the effort.  Pure functions are trivial to test; the tests look like something right out of a textbook, where you build some inputs and look at the output.  Whenever I come across a finicky looking bit of code now, I split it out into a separate pure function and write tests for it.  Frighteningly, I often find something wrong in these cases, which means I’m probably not casting a wide enough net.</p>
<p class="MsoNormal">Understandability and maintainability.  The bounding of both input and output makes pure functions easier to re-learn when needed, and there are less places for undocumented requirements regarding external state to hide.</p>
<p class="MsoNormal">Formal systems and automated reasoning about software will be increasingly important in the future.  <a href="http://altdevblogaday.com/2011/12/24/static-code-analysis/">Static code analysis</a> is important today, and transforming your code into a more functional style aids analysis tools, or at least lets the faster local tools cover the same ground as the slower and more expensive global tools.  We are a “Get ‘er done” sort of industry, and I do not see formal proofs of whole program “correctness” becoming a relevant goal, but being able to prove that certain classes of flaws are not present in certain parts of a codebase will still be very valuable.  We could use some more science and math in our process.</p>
<p class="MsoNormal">Someone taking an introductory programming class might be scratching their head and thinking “aren’t all programs supposed to be written like this?”  The reality is that far more programs are <a href="http://en.wikipedia.org/wiki/Big_ball_of_mud">Big Balls of Mud</a> than not.  Traditional imperative programming languages give you escape hatches, and they get used all the time.  If you are just writing throwaway code, do whatever is most convenient, which often involves global state.  If you are writing code that may still be in use a year later, balance the convenience factor against the difficulties you will inevitably suffer later.  Most developers are not very good at predicting the future time integrated suffering their changes will result in.</p>
<p>&nbsp;</p>
<p class="MsoNormal"><span style="font-size: 18pt">Purity In Practice</span></p>
<p class="MsoNormal">Not everything can be pure; unless the program is only operating on its own source code, at some point you need to interact with the outside world.  It can be fun in a puzzly sort of way to try to push purity to great lengths, but the pragmatic break point acknowledges that side effects are necessary at some point, and manages them effectively.</p>
<p class="MsoNormal">It doesn’t even have to be all-or-nothing in a particular function.  There is a continuum of value in how pure a function is, and the value step from almost-pure to completely-pure is smaller than that from spaghetti-state to mostly-pure.  Moving a function towards purity improves the code, even if it doesn’t reach full purity.  A function that bumps a global counter or checks a global debug flag is not pure, but if that is its only detraction, it is still going to reap most of the benefits.</p>
<p class="MsoNormal">Avoiding the worst in a broader context is generally more important than achieving perfection in limited cases.  If you consider the most toxic functions or systems you have had to deal with, the ones that you know have to be handled with tongs and a face shield, it is an almost sure bet that they have a complex web of state and assumptions that their behavior relies on, and it isn’t confined to their parameters.  Imposing some discipline in these areas, or at least fighting to prevent more code from turning into similar messes, is going to have more impact than tightening up some low level math functions.</p>
<p class="MsoNormal">The process of refactoring towards purity generally involves disentangling computation from the environment it operates in, which almost invariably means more parameter passing.  This seems a bit curious – greater verbosity in programming languages is broadly reviled, and functional programming is often associated with code size reduction.  The factors that allow programs in functional languages to sometimes be more concise than imperative implementations are pretty much orthogonal to the use of pure functions &#8212; garbage collection, powerful built in types, pattern matching, list comprehensions, function composition, various bits of syntactic sugar, etc.  For the most part, these size reducers don’t have much to do with being functional, and can also be found in some imperative languages.</p>
<p class="MsoNormal">You <em>should</em> be getting irritated if you have to pass a dozen parameters into a function; you may be able to refactor the code in a manner that reduces the parameter complexity.</p>
<p class="MsoNormal">The lack of any language support in C++ for maintaining purity is not ideal.  If someone modifies a widely used foundation function to be non-pure in some evil way, everything that uses the function also loses its purity.  This sounds disastrous from a formal systems point of view, but again, it isn’t an all-or-nothing proposition where you fall from grace with the first sin.  Large scale software development is unfortunately statistical.</p>
<p class="MsoNormal">It seems like there is a sound case for a pure keyword in future C/C++ standards.  There are close parallels with const – an optional qualifier that allows compile time checking of programmer intention and will never hurt, and could often help, code generation.  The D programming language does offer a pure keyword:  <a href="http://www.d-programming-language.org/function.html">http://www.d-programming-language.org/function.html</a>  Note their distinction between weak and strong purity – you need to also have const input references and pointers to be strongly pure.</p>
<p class="MsoNormal">In some ways, a language keyword is over-restrictive &#8212; a function can still be pure even if it calls impure functions, as long as the side effects don’t escape the outer function.  Entire programs can be considered pure functional units if they only deal with command line parameters instead of random file system state.</p>
<p class="MsoNormal"><span style="font-size: 18pt">Object Oriented Programming</span></p>
<p class="MsoNormal"><em><a href="https://twitter.com/#%21/mfeathers"><strong><span style="font-family: 'Calibri','sans-serif';color: blue">Michael Feathers</span></strong> <span class="username"><s><span style="color: blue">@</span></s></span><span class="username"><strong><span style="color: blue">mfeathers</span></strong></span> </a>  OO makes code understandable by encapsulating moving parts. FP makes code understandable by minimizing moving parts.</em></p>
<p class="MsoNormal">The “moving parts” are mutating states.  Telling an object to change itself is lesson one in a basic object oriented programming book, and it is deeply ingrained in most programmers, but it is anti-functional behavior.  Clearly there is some value in the basic OOP idea of grouping functions with the data structures they operate on, but if you want to reap the benefits of functional programming in parts of your code, you have to back away from some object oriented behaviors in those areas.</p>
<p class="MsoNormal">Class methods that can’t be const are not pure by definition, because they mutate some or all of the potentially large set of state in the object.  They are not thread safe, and the ability to incrementally poke and prod objects into unexpected states is indeed a significant source of bugs.</p>
<p class="MsoNormal">Const object methods can still be technically pure if you don’t count the implicit <em>const this</em> pointer against them, but many object are large enough to constitute a sort of global state all their own, blunting some of the clarity benefits of pure functions.  Constructors can be pure functions, and generally should strive to be – they take arguments and return an object.</p>
<p class="MsoNormal">At the tactical programming level, you can often work with objects in a more functional manner, but it may require changing the interfaces a bit.  At id we went over a decade with an idVec3 class that had a self-mutating <span style="font-family: 'Courier New'">void Normalize() </span>method, but no corresponding <span style="font-family: 'Courier New'">idVec3 Normalized() const</span> method.  Many string methods were similarly defined as working on themselves, rather than returning a new copy with the operation performed on it – <span style="font-family: 'Courier New'">ToLowerCase(), StripFileExtension(),</span> etc.</p>
<p class="MsoNormal"><span style="font-size: 18pt">Performance Implications</span></p>
<p class="MsoNormal">In almost all cases, directly mutating blocks of memory is the speed-of-light optimal case, and avoiding this is spending some performance.  Most of the time this is of only theoretical interest; we trade performance for productivity all the time.</p>
<p class="MsoNormal">Programming with pure functions will involve more copying of data, and in some cases this clearly makes it the incorrect implementation strategy due to performance considerations.  As an extreme example, you can write a pure <span style="font-family: 'Courier New'">DrawTriangle()</span> function that takes a framebuffer as a parameter and returns a completely new framebuffer with the triangle drawn into it as a result.  Don’t do that.</p>
<p class="MsoNormal">Returning everything by value is the natural functional programming style, but relying on compilers to always perform <a href="http://en.wikipedia.org/wiki/Return_value_optimization">return value optimization</a> can be hazardous to performance, so passing reference parameter for output of complex data structures is often justifiable, but it has the unfortunate effect of preventing you from declaring the returned value as const to enforce <a href="http://en.wikipedia.org/wiki/Single_assignment#Single_assignment">single assignment</a>.</p>
<p class="MsoNormal">There will be a strong urge in many cases to just update a value in a complex structure passed in rather than making a copy of it and returning the modified version, but doing so throws away the thread safety guarantee and should not be done lightly.  List generation is often a case where it is justified.  The pure functional way to append something to a list is to return a completely new copy of the list with the new element at the end, leaving the original list unchanged.  Actual functional languages are implemented in ways that make this not as disastrous as it sounds, but if you do this with typical C++ containers you will die.</p>
<p class="MsoNormal">A significant mitigating factor is that performance today means parallel programming, which usually requires more copying and combining than in a single threaded environment even in the optimal performance case, so the penalty is smaller, while the complexity reduction and correctness benefits are correspondingly larger.  When you start thinking about running, say, all the characters in a game world in parallel, it starts sinking in that the object oriented approach of updating objects has some deep difficulties in parallel environments.  Maybe if all of the object just referenced a read only version of the world state, and we copied over the updated version at the end of the frame…  Hey, wait a minute…</p>
<p>&nbsp;</p>
<p class="MsoNormal"><span style="font-size: 18pt">Action Items</span></p>
<p class="MsoNormal">Survey some non-trivial functions in your codebase and track down every bit of external state they can reach, and all possible modifications they can make.  This makes great documentation to stick in a comment block, even if you don’t do anything with it.  If the function can trigger, say, a screen update through your render system, you can just throw your hands up in the air and declare the set of all effects beyond human understanding.</p>
<p class="MsoNormal">The next task you undertake, try from the beginning to think about it in terms of the real computation that is going on.  Gather up your input, pass it to a pure function, then take the results and do something with it.</p>
<p class="MsoNormal">As you are debugging code, make yourself more aware of the part mutating state and hidden parameters play in obscuring what is going on.</p>
<p class="MsoNormal">Modify some of your utility object code to return new copies instead of self-mutating, and try throwing const in front of practically every non-iterator variable you use.</p>
<p>&nbsp;</p>
<p class="MsoNormal">Additional references:</p>
<p><a href="http://www.haskell.org/haskellwiki/Introduction">http://www.haskell.org/haskellwiki/Introduction</a></p>
<p><a href="http://lisperati.com/">http://lisperati.com/</a></p>
<p><a href="http://www.johndcook.com/blog/tag/functional-programming/">http://www.johndcook.com/blog/tag/functional-programming/</a></p>
<p><a href="http://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf">http://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf</a></p>
<p><a href="http://channel9.msdn.com/Shows/Going+Deep/Lecture-Series-Erik-Meijer-Functional-Programming-Fundamentals-Chapter-1">http://channel9.msdn.com/Shows/Going+Deep/Lecture-Series-Erik-Meijer-Functional-Programming-Fundamentals-Chapter-1</a></p>
<p><a href="http://www.cs.utah.edu/%7Ehal/docs/daume02yaht.pdf">http://www.cs.utah.edu/~hal/docs/daume02yaht.pdf</a></p>
<p><a href="http://www.cs.cmu.edu/%7Ecrary/819-f09/Backus78.pdf">http://www.cs.cmu.edu/~crary/819-f09/Backus78.pdf</a></p>
<p><a href="http://fpcomplete.com/the-downfall-of-imperative-programming/">http://fpcomplete.com/the-downfall-of-imperative-programming/</a></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.altdevblogaday.com/2012/04/26/functional-programming-in-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Static Code Analysis</title>
		<link>http://www.altdevblogaday.com/2011/12/24/static-code-analysis/</link>
		<comments>http://www.altdevblogaday.com/2011/12/24/static-code-analysis/#comments</comments>
		<pubDate>Sat, 24 Dec 2011 05:04:46 +0000</pubDate>
		<dc:creator>John-Carmack</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[/Analyze]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[code analysis]]></category>
		<category><![CDATA[code optimization]]></category>
		<category><![CDATA[Coverity]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[PC-Lint]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[PVS-Studio]]></category>
		<category><![CDATA[static analysis]]></category>
		<category><![CDATA[static code]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://altdevblogaday.com/?p=21879</guid>
		<description><![CDATA[<p>The most important thing I have done as a programmer in recent years is to aggressively pursue static code analysis.  Even more valuable than the hundreds of serious bugs I have prevented with it is the change in mindset about the way I view software reliability and code quality.</p>
<p><a href="http://www.altdevblogaday.com/2011/12/24/static-code-analysis/" class="more-link">Read more on Static Code Analysis&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p>The most important thing I have done as a programmer in recent years is to aggressively pursue static code analysis.  Even more valuable than the hundreds of serious bugs I have prevented with it is the change in mindset about the way I view software reliability and code quality.</p>
<p>It is important to say right up front that quality isn’t everything, and acknowledging it isn’t some sort of moral failing.  <em>Value</em> is what you are trying to produce, and quality is only one aspect of it, intermixed with cost, features, and other factors.  There have been plenty of hugely successful and highly regarded titles that were filled with bugs and crashed a lot; pursuing a Space Shuttle style code development process for game development would be idiotic.  Still, quality does matter.</p>
<p>I have always cared about writing good code; one of my important internal motivations is that of the craftsman, and I always want to improve.  I have read piles of books with dry chapter titles like “Policies , Standards, and Quality Plans”, and my work with Armadillo Aerospace has put me in touch with the very different world of safety critical software development.</p>
<p>Over a decade ago, during the development of Quake 3, I bought a license for PC-Lint and tried using it – the idea of automatically pointing out flaws in my code sounded great.  However, running it as a command line tool and sifting through the reams of commentary that it produced didn’t wind up winning me over, and I abandoned it fairly quickly.</p>
<p>Both programmer count and codebase size have grown by an order of magnitude since then, and the implementation language has moved from C to C++, all of which contribute to a much more fertile ground for software errors.  A few years ago, after reading a number of research papers about modern static code analysis, I decided to see how things had changed in the decade since I had tried PC-Lint.</p>
<p>At this point, we had been compiling at warning level 4 with only a very few specific warnings disabled, and warnings-as-errors forced programmers to abide by it.  While there were some dusty reaches of the code that had years of accumulated cruft, most of the code was fairly modern.  We thought we had a pretty good codebase.</p>
<p><strong>Coverity</strong></p>
<p>Initially, I contacted <a href="http://www.coverity.com/">Coverity</a> and signed up for a demo run.  This is serious software, with the licensing cost based on total lines of code, and we wound up with a quote well into five figures.  When they presented their analysis, they commented that our codebase was one of the cleanest of its size they had seen (maybe they tell all customers that to make them feel good), but they presented a set of about a hundred issues that were identified.  This was very different than the old PC-Lint run.  It was very high signal to noise ratio – most of the issues highlighted were clearly incorrect code that could have serious consequences.</p>
<p>This was eye opening, but the cost was high enough that it gave us pause.  Maybe we wouldn’t introduce that many new errors for it to catch before we ship.</p>
<p><strong>Microsoft /analyze </strong></p>
<p>I probably would have talked myself into paying Coverity eventually, but while I was still debating it, Microsoft preempted the debate by incorporating their <a href="http://msdn.microsoft.com/en-us/library/d3bbz7tz%28v=VS.100%29.aspx">/analyze</a> functionality into the 360 SDK.  /Analyze was previously available as part of the top-end, ridiculously expensive version of Visual Studio, but it was now available to every 360 developer at no extra charge.  I read into this that Microsoft feels that game quality on the 360 impacts them more than application quality on Windows does. :-)</p>
<p>Technically, the Microsoft tool only performs local analysis, so it should be inferior to Coverity’s global analysis, but enabling it poured out <em>mountains</em> of errors, far more than Coverity reported.  True, there were lots of false positives, but there was also a lot of scary, scary stuff.</p>
<p>I started slowly working my way through the code, fixing up first my personal code, then the rest of the system code, then the game code.  I would work on it during odd bits of free time, so the entire process stretched over a couple months.  One of the side benefits of having it stretch out was that it conclusively showed that it was pointing out some very important things – during that time there was an epic multi-programmer, multi-day bug hunt that wound up being traced to something that /analyze had flagged, but I hadn’t fixed yet.  There were several other, less dramatic cases where debugging led directly to something already flagged by /analyze.  These were real issues.</p>
<p>Eventually, I had all the code used to build the 360 executable compiling without warnings with /analyze enabled, so I checked it in as the default behavior for 360 builds.  Every programmer working on the 360 was then getting the code analyzed every time they built, so they would notice the errors themselves as they were making them, rather than having me silently fix them at a later time.  This did slow down compiles somewhat, but /analyze is by far the fastest analysis tool I have worked with, and it is oh so worth it.</p>
<p>We had a period where one of the projects accidentally got the static analysis option turned off for a few months, and when I noticed and re-enabled it, there were piles of new errors that had been introduced in the interim.  Similarly, programmers working just on the PC or PS3 would check in faulty code and not realize it until they got a “broken 360 build” email report.  These were demonstrations that the normal development operations were continuously producing these classes of errors, and /analyze was effectively shielding us from a lot of them.</p>
<p>Bruce Dawson has blogged about working with /analysis a number of times: <a href="http://randomascii.wordpress.com/category/code-reliability/">http://randomascii.wordpress.com/category/code-reliability/</a></p>
<p><strong>PVS-Studio</strong></p>
<p>Because we were only using /analyze on the 360 code, we still had a lot of code not covered by analysis – the PC and PS3 specific platform code, and all the utilities that only ran on the PC.</p>
<p>The next tool I looked at was <a href="http://www.viva64.com/en/pvs-studio/">PVS-Studio</a>.  It has good integration with Visual Studio, and a convenient demo mode (try it!).  Compared to /analyze, PVS-Studio is painfully slow, but it pointed out a number of additional important errors, even on code that was already completely clean to /analyze.  In addition to pointing out things that are logically errors, PVS-Studio also points out a number of things that are common patterns of programmer error, even if it is still completely sensible code.  This is almost guaranteed to produce some false positives, but damned if we didn’t have instances of those common error patterns that needed fixing.</p>
<p>There are a number of good articles on the PVS-Studio <a href="http://www.viva64.com/en/developers-resources/">site</a>, most with code examples drawn from open source projects demonstrating exactly what types of things are found.   I considered adding some representative code analysis warnings to this article, but there are already better documented examples present there.  Go look at them, and don&#8217;t smirk and think &#8220;I would never write that!&#8221;</p>
<p><strong>PC-Lint</strong></p>
<p>Finally, I went back to <a href="http://www.gimpel.com/html/pcl.htm">PC-Lint</a>, coupled with  <a href="http://www.riverblade.co.uk/products/visual_lint/index.html">Visual Lint</a> for IDE integration.  In the grand unix tradition, it can be configured to do just about anything, but it isn’t very friendly, and generally doesn’t “just work”.  I bought a five-pack of licenses, but it has been problematic enough that  I think all the other developers that tried it gave up on it.  The flexibility does have benefits – I was able to configure it to analyze all of our PS3 platform specific code, but that was a tedious bit of work.</p>
<p>Once again, even in code that had been cleaned by both /analyze and PVS-Studio, new errors of significance were found.  I made a real effort to get our codebase lint clean, but I didn’t succeed.  I made it through all the system code, but I ran out of steam when faced with all the reports in the game code.  I triaged it by hitting the classes of reports that I worried most about, and ignored the bulk of the reports that were more stylistic or potential concerns.</p>
<p>Trying to retrofit a substantial codebase to be clean at maximum levels in PC-Lint is probably futile.  I did some “green field” programming where I slavishly made every picky lint comment go away, but it is more of an adjustment than most experienced C/C++ programmers are going to want to make.  I still need to spend some time trying to determine the right set of warnings to enable to let us get the most benefit from PC-Lint.</p>
<p><strong>Discussion</strong></p>
<p>I learned a lot going through this process.  I fear that some of it may not be easily transferable, that without personally going through hundreds of reports in a short amount of time and getting that sinking feeling in the pit of your stomach over and over again, “we’re doing OK” or “it’s not so bad” will be the default responses.</p>
<p>The first step is fully admitting that the code you write is riddled with errors.  That is a bitter pill to swallow for a lot of people, but without it, most suggestions for change will be viewed with irritation or outright hostility.  You have to <em>want</em> criticism of your code.</p>
<p>Automation is necessary.  It is common to take a sort of smug satisfaction in reports of colossal failures of automatic systems, but for every failure of automation, the failures of humans are legion.  Exhortations to “write better code” plans for more code reviews, pair programming, and so on just don’t cut it, especially in an environment with dozens of programmers under a lot of time pressure.  The value in catching even the small subset of errors that are tractable to static analysis <em>every single time</em> is huge.</p>
<p>I noticed that each time PVS-Studio was updated, it found something in our codebase with the new rules.  This seems to imply  that if you have a large enough codebase, any class of error that is syntactically legal probably exists there.  In a large project, code quality is every bit as statistical as physical material properties – flaws exist all over the place, you can only hope to minimize the impact they have on your users.</p>
<p>The analysis tools are working with one hand tied behind their back, being forced to infer information from languages that don’t necessarily provide what they want, and generally making very conservative assumptions.  You should cooperate as much as possible – favor indexing over pointer arithmetic, try to keep your call graph inside a single source file, use explicit annotations, etc.  Anything that isn’t crystal clear to a static analysis tool probably isn’t clear to your fellow programmers, either.  The classic hacker disdain for “bondage and discipline languages” is short sighted – the needs of large, long-lived, multi-programmer projects are just different than the quick work you do for yourself.</p>
<p>NULL pointers are the biggest problem in C/C++, at least in our code.  The dual use of a single value as both a flag and an address causes an incredible number of fatal issues.  C++ references should be favored over pointers whenever possible; while a reference is “really” just a pointer, it has the implicit contract of being not-NULL.  Perform NULL checks when pointers are turned into references, then you can ignore the issue thereafter.  There are a lot of deeply ingrained game programming patterns that are just dangerous, but I’m not sure how to gently migrate away from all the NULL checking.</p>
<p>Printf format string errors were the second biggest issue in our codebase, heightened by the fact that passing an idStr instead of idStr::c_str() almost always results in a crash, but annotating all our variadic functions with /analyze annotations so they are properly type checked kills this problem dead.  There were dozens of these hiding in informative warning messages that would turn into crashes when some odd condition triggered the code path, which is also a comment about how the code coverage of our general testing was lacking.</p>
<p>A lot of the serious reported errors are due to modifications of code long after it was written.  An incredibly common error pattern is to have some perfectly good code that checks for NULL before doing an operation, but a later code modification changes it so that the pointer is used again without checking.  Examined in isolation, this is a comment on code path complexity, but when you look back at the history, it is clear that it was more a failure to communicate preconditions clearly to the programmer modifying the code.</p>
<p>By definition, you can’t focus on everything, so focus on the code that is going to ship to customers, rather than the code that will be used internally.  Aggressively migrate code from shipping to isolated development projects.  There was a paper recently that noted that all of the various code quality metrics correlated at least as strongly with code size as error rate, making code size alone give essentially the same error predicting ability.  Shrink your important code.</p>
<p>If you aren’t deeply frightened about all the additional issues raised by concurrency, you aren’t thinking about it hard enough.</p>
<p>It is impossible to do a true control test in software development, but I feel the success that we have had with code analysis has been clear enough that I will say plainly <strong>it is irresponsible to not use it</strong>.  There is objective data in automatic console crash reports showing that Rage, despite being bleeding edge in many ways, is remarkably more robust than most contemporary titles.  The PC launch of Rage was unfortunately tragically flawed due to driver problems &#8212; I’ll wager AMD does not use static code analysis on their graphics drivers.</p>
<p>The takeaway action should be:  If your version of Visual Studio has /analyze available, turn it on and give it a try.  If I had to pick one tool, I would choose the Microsoft option.  Everyone else working in Visual Studio, at least give the PVS-Studio demo a try.  If you are developing commercial software, buying static analysis tools is money well spent.</p>
<p>A final parting comment from twitter:</p>
<p><a href="http://twitter.com/#%21/dave_revell"><strong>Dave Revell</strong> <span style="text-decoration: line-through;">@</span><strong>dave_revell</strong> </a> The more I push code through static analysis, the more I&#8217;m amazed that computers boot at all.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.altdevblogaday.com/2011/12/24/static-code-analysis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Parallel Implementations</title>
		<link>http://www.altdevblogaday.com/2011/11/22/parallel-implementations/</link>
		<comments>http://www.altdevblogaday.com/2011/11/22/parallel-implementations/#comments</comments>
		<pubDate>Tue, 22 Nov 2011 18:27:17 +0000</pubDate>
		<dc:creator>John-Carmack</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[game development]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://altdevblogaday.com/?p=20465</guid>
		<description><![CDATA[<p>I used to <a href="http://cam.ly/blog/2010/12/code-fearlessly/">Code Fearlessly</a> all the time, tearing up everything whenever I had a thought about a better way of doing something.  There was even a bit of pride there &#8212; &#8220;I&#8217;m not afraid to suffer consequences in the quest to Do The Right Thing!&#8221;  Of course, to be honest, the consequences usually fell on a more junior programmer who had to deal with an irate developer that had something unexpectedly stop working when I tore up the code to make it &#8220;better&#8221;.</p>
<p><a href="http://www.altdevblogaday.com/2011/11/22/parallel-implementations/" class="more-link">Read more on Parallel Implementations&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p>I used to <a href="http://cam.ly/blog/2010/12/code-fearlessly/">Code Fearlessly</a> all the time, tearing up everything whenever I had a thought about a better way of doing something.  There was even a bit of pride there &#8212; &#8220;I&#8217;m not afraid to suffer consequences in the quest to Do The Right Thing!&#8221;  Of course, to be honest, the consequences usually fell on a more junior programmer who had to deal with an irate developer that had something unexpectedly stop working when I tore up the code to make it &#8220;better&#8221;.</p>
<p>Sure, with everything in source control you can roll back the changes if it catastrophically breaks, but if you did succeed in making some aspect better, there is an incentive to keep pushing forward, even if there is a bit of suffering involved.  Somewhat more subtly, there are all sorts of opportunities to avoid making honest comparisons between the new way and the old way.  Rolling back code and rebuilding to run a test is a pain, and you aren’t going to do it very often, even if you have a suspicion that things aren’t working quite as well in a particular case you hadn’t considered during the rewrite.</p>
<p>What I try to do nowadays is to implement new ideas in parallel with the old ones, rather than mutating the existing code.  This allows easy and honest comparison between them, and makes it trivial to go back to the old reliable path when the spiffy new one starts showing flaws.  The difference between changing a console variable to get a different behavior versus running an old exe, let alone reverting code changes and rebuilding, is significant.</p>
<p>For some tasks, this is pretty obvious.  If you have a ray tracer, it isn&#8217;t hard to see an interface that allows you to have the Trace() function use various kD tree / BVH / BSP back ends, and a similar case can be made for the processing code that builds accelerator structures for them.  Missing some pixels?  Change over to the other implementation and check it there.</p>
<p>However, some of my most effective uses of this strategy have been more aggressive.  Over the years, I have done a number of hardware acceleration conversions from software rendering engines.  In the old days, I would basically start from scratch, first implementing the environment rendering, then the characters, then the special effects.  There were always lots of little features that got forgotten, and comparing against the original meant playing through the game on two systems at once.</p>
<p>The last two times I did this, I got the software rendering code running on the new platform first, so everything could be tested out at low frame rates, then implemented the hardware accelerated version in parallel, setting things up so you could instantly switch between the two at any time.  For a mobile OpenGL ES application being developed on a windows simulator, I opened a completely separate window for the accelerated view, letting me see it simultaneously with the original software implementation.  This was a <em>very</em> significant development win.</p>
<p>If the task you are working on can be expressed as a pure function that simply processes input parameters into a return structure, it is easy to switch it out for different implementations.  If it is a system that maintains internal state or has multiple entry points, you have to be a bit more careful about switching it in and out.  If it is a gnarly mess with lots of internal callouts to other systems to maintain parallel state changes, then you have some cleanup to do before trying a parallel implementation.</p>
<p>There are two general classes of parallel implementations I work with:  The reference implementation, which is much smaller and simpler, but will be maintained continuously, and the experimental implementation, where you expect one version to “win” and consign the other implementation to source control in a couple weeks after you have some confidence that it is both fully functional and a real improvement.</p>
<p>It is completely reasonable to violate some generally good coding rules while building an experimental implementation – copy, paste, and find-replace rename is actually a good way to start.  Code fearlessly on the copy, while the original remains fully functional and unmolested.  It is often tempting to shortcut this by passing in some kind of option flag to existing code, rather than enabling a full parallel implementation.  It is a  grey area, but I have been tending to find the extra path complexity with the flag approach often leads to messing up both versions as you work, and you usually compromise both implementations to some degree.</p>
<p>Every single time I have undertaken a parallel implementation approach, I have come away feeling that it was beneficial, and I now tend to code in a style that favors it.  Highly recommended.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.altdevblogaday.com/2011/11/22/parallel-implementations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.414 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-05-17 03:07:28 -->
<!-- Compression = gzip -->
