<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>C on Games From Within</title><link>https://gamesfromwithin.com/category/c/</link><description>Recent content in C on Games From Within</description><generator>Hugo</generator><language>en-us</language><copyright>2004–2026 Noel Llopis</copyright><lastBuildDate>Tue, 04 Jan 2011 00:00:00 +0000</lastBuildDate><atom:link href="https://gamesfromwithin.com/category/c/index.xml" rel="self" type="application/rss+xml"/><item><title>Data-Oriented Design Now And In The Future</title><link>https://gamesfromwithin.com/data-oriented-design-now-and-in-the-future/</link><pubDate>Tue, 04 Jan 2011 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/data-oriented-design-now-and-in-the-future/</guid><description>&lt;p&gt;&lt;em&gt;There has been a lot of recent discussion (and criticism) on Data Oriented Design recently. I want to address some of the issues that have been raised, but before that, I&amp;rsquo;ll start with this reprint from my most recent Game Developer Magazine. If you have any questions you&amp;rsquo;d like addressed, add write a comment and I&amp;rsquo;ll try to answer everything I can.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;a href="https://gamesfromwithin.com/data-oriented-design/"&gt;Last year I wrote about the basics of Data-Oriented Design&lt;/a&gt; (see the September 2009 issue of Game Developer). In the time since that article, Data-Oriented Design has gained a lot of traction in game development and many of teams are thinking in terms of data for some of the more performance-critical systems.&lt;/p&gt;</description><content:encoded><![CDATA[<p><em>There has been a lot of recent discussion (and criticism) on Data Oriented Design recently. I want to address some of the issues that have been raised, but before that, I&rsquo;ll start with this reprint from my most recent Game Developer Magazine. If you have any questions you&rsquo;d like addressed, add write a comment and I&rsquo;ll try to answer everything I can.</em></p>
<p> </p>
<p><a href="/data-oriented-design/">Last year I wrote about the basics of Data-Oriented Design</a> (see the September 2009 issue of Game Developer). In the time since that article, Data-Oriented Design has gained a lot of traction in game development and many of teams are thinking in terms of data for some of the more performance-critical systems.</p>
<p>As a quick recap, the main goal of Data-Oriented Design is achieving high-performance on modern hardware platforms. Specifically, that means making good use of memory accesses, multiple cores, and removing any unnecessary code. A side effect of Data-Oriented Design is that code becomes more modular and easier to test.</p>
<p>Data-Oriented Design concentrates on the input data available and the output data that needs to be generated. Code is not something to focus on (like traditional Computer Science), but is something that is written to transform the input data into the output data in an efficient way. In modern hardware, that often means applying the same code to large, contiguous blocks of homogeneous memory.</p>
<h3 id="applying-data-oriented-design">Applying Data-Oriented Design</h3>
<p><img alt="data.jpg" loading="lazy" src="/data-oriented-design-now-and-in-the-future/images/data.jpg">Itâ€™s pretty easy to apply these ideas to a self-contained system that already works over mostly-homogeneous data. Most particle systems in games are probably designed that way because one of their main goals is to be very efficient and handle a large number of particles at high framerates. Sound processing is another system that is naturally implemented thinking about data first and foremost.</p>
<p>So, whatâ€™s stopping us from applying it to all the performance-sensitive systems in a game code base? Mostly just the way we think about the code. We need to be ready to really look at the data and be willing to split up the code into different phases. Letâ€™s take a high-level example and see how the code would have to be restructured when optimizing for data access.</p>
<p>Listing 1 shows pseudocode for what could be a typical update function for a generic game AI. To make things worse, that function might even be virtual and different types of entities might implement it in different ways. Letâ€™s ignore that for now and concentrate on what it does. In particular, the pseudocode highlights that, as part of the entity update, it does many conditional ray casting queries, and also updates some state based on the results of those queries. In other words, weâ€™re confronted with the typical tree-traversal code structure so common in Object-Oriented Programming.</p>
<pre tabindex="0"><code>void AIEntity::Update(float dt)
{
    DoSomeProcessing();
    if (someCondition &amp;&amp; Raycast(world))
       DoSomething();
    if (someOtherCondition &amp;&amp; BunchOfRayCasts(world))
       DoSomethingElse();
    UpdateSomeOtherStuff();
}
</code></pre><p><em>Listing 1</em></p>
<p>Ray casts against the world are a very common operation for game entities. Thatâ€™s how they â€œseeâ€ whatâ€™s around them and thatâ€™s what allows them to react correctly to their surroundings. Unfortunately, ray casting is a very heavy weight operation, and it involves potentially accessing many different areas in memory: a spatial data structure, other entity representations, polygons in a collision mesh, etc.</p>
<p>Additionally, the entity update function would be very hard to paralellize on multiple cores. Itâ€™s unclear how much data is read or written in that function, and some of that data (like the world data structure) might be particularly hard and expensive to protect from updates from multiple threads.</p>
<p>If we re-organize things a bit, we can significantly improve performance and paralellization.</p>
<h3 id="break-up-and-batch">Break Up And Batch</h3>
<p>Without seeing any of the details of whatâ€™s going on inside the entity update, we can see the raycasts sticking out like a sore thumb in the middle. A raycast operation is fairly independent of anything else related to the entity, itâ€™s heavyweight, and there could be many of them, so itâ€™s a perfect candidate to break up into a separate step.</p>
<p>Listing 2 shows how the broken up entity update code would look like. The update is now split in two different passes: The first pass does some of the updating that can be done independently of any ray casts, and decides which, if any, raycasts need to be performed sometime this frame.</p>
<pre tabindex="0"><code>void AIEntity::InitialUpdate(float dt, RayCastQueries&amp; queries)
{
    DoSomeProcessing();
    if (someCondition)
        AddRayCastQuery(queries);
    if (someOtherCondition)
        AddBunchOfRayCasts(queries);
}

void AIEntity::FinalUpdate(const RayCastResults&amp; results)
{
    UpdateSomeOtherStuff(results);
}
</code></pre><p><em>Listing 2</em></p>
<p>The game code in charge of updating the game processes all AI entities in batches (Listing 3). So instead of calling InitialUpdate(), solve ray casts, and FinalUpdate() for each entity, it iterates over all the AI entities calling InitialUpdate() and adds all the raycast query requests to the output data. Once it has collected all the raycast queries, it can process them all at once and store their results. Finally, it does one last pass and calls FinalUpdate() with the raycast results on each entity.</p>
<pre tabindex="0"><code>RayCastQueries queries;
for (int i=0; i&lt;entityCount; ++i)
    entities[i].InitialUpdate(dt, queries);

// Other update that might need raycasts

RayCastResults results;
for (int i=0; i&lt;queries.count; ++i)
    PerformRayCast(queries[i], results);

for (int i=0; i&lt;entityCount; ++i)
    entities[i].FinalUpdate(results);
</code></pre><p><em>Listing 3</em></p>
<p>By removing the raycast calls from within the entity update function, weâ€™ve shortened the call tree significantly. The functions are more self-contained, easier to understand, and probably much more efficient because of better cache utilization. You can also see how it would be a lot easier to parallelize things now by sending all raycasts to one core while another core is busy updating something unrelated (or maybe by spreading all raycasts across multiple cores, depending on your level of granularity).</p>
<p>Note that after calling InitialUpdate() on all entities, we could do some processing on other game objects that might also need raycast queries and collect them all. That way, we can batch all the raycasts at compute them all at once. For years, weâ€™ve been drilled by graphics hardware manufacturers how we should batch our render calls and avoid drawing individual polygons. This is the same way: By batching all raycasts in a single call, we have the potential to achieve much higher performance.</p>
<h3 id="splitting-things-up">Splitting Things Up</h3>
<p>Have we really gained much by reorganizing the code this way? Weâ€™re doing two full passes over the AI entities, so wouldnâ€™t that be worse from a memory point of view? Ultimately you need to measure it and compare the two. In modern hardware platforms, I would expect performance to be better because, even though weâ€™re traversing through the entities twice, weâ€™re using the code cache much better and weâ€™re accessing them sequentially (which allows us to pre-fetch the next one too).</p>
<p>If this is the only change we make to the entity update, and the rest of the code is the usual deep tree traversal code, we might not have gained much because weâ€™re still blowing the cache limits with every update. We might need to apply the same design principles to the rest of the update function to start seeing performance improvements. But at the very least, even with this small change, we have made it easier to parallelize.</p>
<p>One thing weâ€™ve gained now is the ability to modify our data to fit the way weâ€™re using it, and thatâ€™s the key to big performance gains. For example, after seeing how the entity is updated in two separate passes, you might notice that only some of the data that was stored in the entity object is touched from the first update, and the second pass accesses more specific data.</p>
<p>At that point we can split up the entity class into two different sets of data. One of the most difficult things at this point is naming these sets data in some meaningful way. Theyâ€™re not representing real objects or real-world concepts anymore, but different aspects of a concept, broken down purely by how the data is processed. So what before was an AIEntity, can now become a EntityInfo (containing things like position, orientation, and some high-level data) and AIState (with the current goals, orders, paths to follow, enemies targeted, etc).</p>
<p>The overall update function now deals with EntityInfo structures in the first pass, and AIState structures in the second pass, making it much more cache friendly and efficient.</p>
<p>Realistically, both the first and second passes will have to access some common data (for example the entity current state: fleeing, engaged, exploring, idle, etc). If itâ€™s only a small amount of data, the best solution might be to simply duplicate that data on both structures (going against all â€œcommon wisdomâ€ in Computer Science). If the common data is larger or is read-write, it might make more sense to give it separate data structure of its own.</p>
<p>At this point, a different kind of complexity is introduced: Keeping track of all the relationships from the different structures. This can be particularly challenging while debugging because some of the data belonging to the same logical entity isnâ€™t stored in the same structure and itâ€™s harder to explore in a debugger. Even so, making good use of indices and handles makes this problem much more manageable (see Managing Data Relationships in the September 2008 issue of Game Developer).</p>
<h3 id="conditional-execution">Conditional Execution</h3>
<p>So far things are pretty simple because weâ€™re assuming that every AI entity needs both updates and some ray casts. Thatâ€™s not very realistic because entities are probably very bursty: sometimes they need a lot of ray casts, and sometimes theyâ€™re idle or following orders and donâ€™t need any for a while. We can deal with this situation by adding a conditional execution to the second update function.</p>
<p>The easiest way to conditionally execute the update would be to add an extra output parameter to the FirstUpdate() function indicating whether the entity needs a second update or not. The same information could be derived form the calling code depending on whether there were any raycasts queries added. Then, in the second pass, we only update those entities that appear in the list of entities requiring a second update.</p>
<p>The biggest drawback of this approach is that the second update went from traversing memory linearly to skipping over entities, potentially affecting cache performance. So what we thought was going to be a performance optimization ended up making things slower. Unless weâ€™re gaining a significant performance improvement, itâ€™s often better to simply do the work for all entities whether they need it or not. However, if on average less than 10 or 20 percent of the entities need a ray cast, then it might be worth avoiding doing the second update on all the other entities and paying the conditional execution penalty.</p>
<p>If the number of entities to be updated in the second pass is fairly small, another approach would be to copy all necessary data from the first pass into a new temporary buffer. The second pass can then process that data sequentially without any performance penalties and it would completely offset the performance hit of copying the data.</p>
<p>Finally, another alternative, especially if the conditional execution remains fairly similar from frame to frame, is to relocate entities that need raycasting together. That way the copying is minimal (swapping an entity to a new location in the array whenever it needs a raycast), and we still get the benefit of the sequential second update. For this to work all your entities need to be fully relocatable, which means working with handles or some other indirection, or updating all the references to the entities that swapped places.</p>
<h3 id="different-modes">Different Modes</h3>
<p>What if the entity can be in several, totally different modes of execution? Even if itâ€™s the same type of entity, traversing through them linearly calling the update function could end up using completely different code for each of them, so it will result in poor code cache performance.</p>
<p>There are several approached we can take in a situation like that:</p>
<ul>
<li>If the different execution modes also are tied to different parts of the entity data, we could treat them as if they were completely different entities and break each of their data components apart. That way, we can iterate through each type separately and get all the performance benefits.</li>
<li>If the data is mostly the same, and itâ€™s just the code that changes, we could keep all the entities in the same memory block, but rearrange them so that entities in the same mode are next to each other. Again, if you can relocate your data, this is very easy and efficient (it only requires swapping a few entities whenever the state changes).</li>
<li>Leave it alone! Ultimately, Data-Oriented Design is about thinking about the data and how it affects your program. It doesnâ€™t mean you always have to optimize every aspect of it, especially if the gains arenâ€™t significant enough to warrant the added complexity.</li>
</ul>
<h3 id="the-future">The Future</h3>
<p>Is thinking about a program in terms of data and doing these kind of optimizations a good use of our time? Is this all going to go away in the near future as hardware improves? As far as we can tell right now, the answer is a definite no. Efficient memory access with a single CPU is a very complicated problem, and matters get much worse as we add more cores. Also, the amount of transistors in CPUs (which is a rough measure of power) continues to increase much faster than memory access time. That tells us that, barring new technological breakthroughs, weâ€™re going to be dealing with this problem for a long time. This is a problem we need to deal with right now and build our technology around it.</p>
<p>There are some things Iâ€™d like to see in the future to make Data-Oriented Design easier. We can all dream up of a new language that will magically allow for great memory access and easy paralellization, but replacing C/C++ and all existing libraries is always going to be a really hard sell. Historically, the best advances in game technology have been incremental, not throwing away existing languages, tools, and libraries (thatâ€™s why weâ€™re still stuck with C++ today).</p>
<p>Here are two things that could be done right now and work with our existing codebases. I know a lot of developers are working on similar systems in their projects, but it would be great to have a common implementation released publicly so we can all build on top of them.</p>
<h3 id="language">Language</h3>
<p>Even though a functional language might be ideal, either created from scratch or reusing an existing one, we could temporarily extend C to fit our needs. I would like to see a set of C extensions where functions have clearly defined inputs and outputs, and code inside a function is not allowed to access any global state or call any code outside that function (other than local helper functions defined in the same scope). This could be done as a preprocessor or a modified C compiler, so it remains very compatible with existing libraries and code.</p>
<pre tabindex="0"><code>void FirstEntityUpdate(input Entities* entities, input int entityCount, output RayCastQueries* queries, output int queryCount);
</code></pre><p>Dependencies between functions would be expressed by tying the outputs of some functions to the input of other functions. This could be done in code or through the use of GUI tools that help developers manage data relationships visually. That way we can construct a dependency diagram of all the functions involved in every frame.</p>
<h3 id="scheduler">Scheduler</h3>
<p>Once we have the dependencies for every function, we can create a directed acyclic graph (DAG) from it, which would give us a global view of how data is processed every frame. At that point, instead of running functions manually, we can leave that job in the hands of a scheduler.</p>
<p>The scheduler has full information about all the functions as well as the number of available cores (and information from the previous frame execution if we want to use that as well). It can determine the critical path through the DAG and optimize the scheduling of the tasks so the critical path is always being worked on. If temporary memory buffers are a limitation for our platform, the scheduler can take that into account and trade some performance time for a reduced memory footprint.</p>
<p>Just like the language, the scheduler would be a very generic component, and could be made public. Developers could use it as a starting point, build on top of it, and add their own rules for their specific games and platforms.</p>
<p> </p>
<p>Even if weâ€™re not ready to create those reusable components, every developer involved in creating high-performance games should be thinking about data in their games right now. Data is only going to get more important in the future as the next generation of consoles and computers rolls in.</p>
<p> </p>
<p><em>This article was originally printed in the September 2010 issue of <a href="http://gdmag.com">Game Developer</a>.</em></p>]]></content:encoded></item><item><title>Start Pre-allocating And Stop Worrying</title><link>https://gamesfromwithin.com/start-pre-allocating-and-stop-worrying/</link><pubDate>Mon, 25 Oct 2010 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/start-pre-allocating-and-stop-worrying/</guid><description>&lt;p&gt;&lt;em&gt;One of the more frequent questions I receive is what kind of memory allocation strategy I use in my games. The quick answer is none (at least frame to frame, I do some allocation at the beginning of each level on a stack-based allocator). This reprint of one of my Inner Product column covers quite well how I feel about memory allocation.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve all had things nagging us in the back of our minds. They&amp;rsquo;re nothing we have to worry about this very instant, just something we need to do sometime in the future. Maybe that&amp;rsquo;s changing those worn tires in the car, or making an appointment with the dentist about that tooth that has been bugging you on and off.&lt;/p&gt;</description><content:encoded><![CDATA[<p><em>One of the more frequent questions I receive is what kind of memory allocation strategy I use in my games. The quick answer is none (at least frame to frame, I do some allocation at the beginning of each level on a stack-based allocator). This reprint of one of my Inner Product column covers quite well how I feel about memory allocation.</em></p>
<p>We&rsquo;ve all had things nagging us in the back of our minds. They&rsquo;re nothing we have to worry about this very instant, just something we need to do sometime in the future. Maybe that&rsquo;s changing those worn tires in the car, or making an appointment with the dentist about that tooth that has been bugging you on and off.</p>
<p>Dynamic memory allocation is something that falls in that category for most programmers. We all know we can&rsquo;t just go on allocating memory willy-nilly whenever we need it, yet we put off dealing with it until the end of the project. By that time, deadlines are piling on the pressure and it&rsquo;s usually too late to make significant changes. With a little bit of forethought and pre-planning, we can avoid those problems and be confident our game is not going to run out of memory in the most inopportune moment.</p>
<h3 id="on-demand-dynamic-memory-allocation">On-Demand Dynamic Memory Allocation</h3>
<p><img alt="memory-all-ranks.jpg" loading="lazy" src="/start-pre-allocating-and-stop-worrying/images/memory-all-ranks.jpg">The easiest way to get started with memory management is to allocate memory dynamically whenever you need it. This is the approach many software engineering books consider as ideal and it&rsquo;s often encouraged in Computer Science classes.</p>
<p>It&rsquo;s certainly an easy approach to use. Need a new animation instance when the player is landing on a ledge? Allocate it. Need a new sound when we reach the goal? Just allocate another one!</p>
<p>On-demand dynamic memory allocation can help to keep memory usage to a minimum, because, you only allocate the memory that you need and no more. In practice it&rsquo;s not quite as neat and tidy because there can be a surprisingly large amount of overhead per allocation, which adds up if programmers become really allocation-happy.</p>
<p>It&rsquo;s also a good way to shoot yourself in the foot.</p>
<p>Games don&rsquo;t live inside a Computer Science textbook, so we have to deal with real world limitations, which make this approach cumbersome, clunky, and potentially disastrous. What can go wrong with on-demand dynamic memory allocation? Almost everything!</p>
<h4 id="limited-memory">Limited Memory</h4>
<p>Games, or any software for that matter, run on machines with limited amounts of memory. As long as you know what that limit is, and you keep extremely careful track of your memory usage, you can remain under the limit. However, since the game is allocating memory any time it needs it, there will most likely come a time when the game tries to allocate a new block but there is no memory left. What can you do then? Nothing easy I&rsquo;m afraid. You can try to free an older memory block and allocate the new one there, or you can try to make your game tolerant to running out of memory. Both those solutions are very complex and difficult to implement correctly.</p>
<p>Even setting memory budgets and sticking to them can be very difficult. How can a designer know that a given particle system isn&rsquo;t going to run out of memory? Are these AI units going to create too many pathfinding objects and crash the game? Hard to say until we run the game in all possible combinations. And even then, how do you know it isn&rsquo;t going to crash five minutes later? Or ten? It&rsquo;s almost impossible to know for certain.</p>
<p>If you insist in using this approach, at the very least, you should tag all memory allocations, so you have an idea of how memory is being used. You can either tag each allocation based on what system initiated it (physics, textures, animation, sound, AI, etc) or even on the filename where it originated, which has the advantage that it can be automated and should still give you a good picture of the overall memory usage.</p>
<h4 id="memory-fragmentation">Memory Fragmentation</h4>
<p>Even if you take lots of pain not to go over your the available memory, you might still run into trouble because of memory fragmentation. You might have enough memory for a new allocation, but in the form of many small memory blocks instead of a large contiguous one. Unless you provide your own memory allocation mechanism, fragmentation is something that is very hard to track on your own, so you can&rsquo;t even be ready for it until the allocation fails.</p>
<h4 id="virtual-memory">Virtual Memory</h4>
<p>Virtual memory could solve all those problems. In theory, if you run out of real memory, the operating system swaps out some older, unused pages to disk and makes room for the new memory you requested. In practice, it&rsquo;s just a bad caching scheme because it can be triggered at the worst possible moment, and it doesn&rsquo;t know about what data it&rsquo;s swapping out or how your game uses it.</p>
<p>Games, unlike most other software, have a &ldquo;soft realtime&rdquo; requirement: The game needs to keep updating at an acceptable interactive rate, which is somewhere around 15 or more frames per second. That means that gamers are going to make a trip to the store to return your game if it pauses for a couple of seconds every few minutes to &ldquo;make some room&rdquo; for new memory. So relying on virtual memory isn&rsquo;t a particularly attractive solution.</p>
<p>Additionally, lots of games run in platforms with fixed amounts of RAM and no virtual memory. So when memory runs out, things won&rsquo;t get slow and chuggy, they&rsquo;ll crash hard. When the memory is gone, it&rsquo;s really gone.</p>
<h4 id="performance-problems">Performance Problems</h4>
<p>There are some performance issues that are relatively easy to track down and fix. Usually ones that occur every frame and are happening in a single spot: some expensive operation, a O(n3) algorithm, etc. Then there are performance problems introduced by dynamic memory allocations, which can be really hard to track down.</p>
<p>Standard malloc returns memory pretty quickly, and usually doesn&rsquo;t ever register on the the profiler. Every so often though, whenever the game has been running for a while and memory is pretty fragmented, it can spike up and cause a significant delay for just a frame. Trying to track down those spikes has caused more than one programmer to age prematurely. You can avoid some of those problems by using your own memory manager, but don&rsquo;t attempt to write a generic one yourself from scratch. Instead start with some of the ones listed in the references.</p>
<p>Malloc spikes are not the only source of performance problems. Allocating many small blocks of memory can lead to bad cache coherence when the game code access them sequentially. This problem usually manifests itself as a general slowdown that can&rsquo;t be narrowed down in the profiler. With today&rsquo;s hardware of slow memory systems and deep caches, good memory access patterns are more important than ever.</p>
<h4 id="keeping-track-of-memory">Keeping Track Of Memory</h4>
<p>Another source of problems with dynamic memory allocation are bugs in the logic that keeps track of the allocated memory blocks. If we forget to free some of them, our program will have memory leaks and has the potential to run out of memory.</p>
<p>The flip side of memory leaks are invalid memory access. If we free a memory block and later we access it as if it were allocated, we&rsquo;ll either get a memory access exception, or we&rsquo;ll manage to corrupt our own game.</p>
<p>Some techniques, such as reference counting and garbage collection can help keep track of memory allocations, but introduce their own complexities and overhead.</p>
<h3 id="introducing-pre-allocation">Introducing Pre-allocation</h3>
<p>On the opposite corner of the boxing ring is the purely pre-allocated game. It excels at everything that the dynamically-allocated game is weak at, but it has a few weaknesses of its own. All in all, it&rsquo;s probably a much safer approach for most games though.</p>
<p>The idea behind a pre-allocation memory strategy is to allocate everything once and never have to do any dynamic allocations in the middle of the game. Usually you grab as big a block of memory as you can, and then you carve it out to suit your game&rsquo;s needs.</p>
<p>Some advantages are very clear: no performance penalties, knowing exactly how your memory is used, never running out of memory, and no memory fragmentation to worry about. There are some other more subtle advantages, such as being able to put data in contiguous areas of memory to get best cache coherency, or having blazingly-fast load times by loading a baked image of a level directly into memory.</p>
<p>The main drawback of pre-allocation is that is more complex to implement than the dynamic allocation approach and it takes some planning ahead.</p>
<h4 id="know-your-data">Know Your Data</h4>
<p>For preallocation to work, you need to know ahead of time how much of every type of data you will need in the game. That can be a daunting proposition, especially to those used to a more dynamic approach. However, with a good data baking system (see last month&rsquo;s Inner Product column), you can get a global view of each level and figure out how big things need to be.</p>
<p>There is one important design philosophy that needs to be adopted for preallocation to work: Everything in the game has to be bounded. That shouldn&rsquo;t feel too restrictive; after all, the memory in your target platform is bounded, as well as every single resource. That means that everything that can create new objects, including high-level game constructs, should operate on a fixed number of them. This might seem like an implementation detail, but it often bubbles up to what&rsquo;s exposed to game designers. A common example is an enemy spawner. Instead of designing a spawner with an emission rate, it should have a fixed number of enemies it can spawn (and potentially reuse them after they&rsquo;re dead).</p>
<h4 id="potentially-wasted-space">Potentially Wasted Space</h4>
<p>If you allocate enough data for the worst case in your game, that can lead to a lot of unused data most of the time. That&rsquo;s only an issue if that unused data is preventing you from adding more content to the game. We might initially balk at the idea of having 2000 preallocated enemies when we&rsquo;re only going to see 10 of them at once. But when you realize that each of those enemies is only taking 256 bytes and the total overhead is 500 KB, which can be easily accommodated in most modern platforms today.</p>
<p>Preallocation doesn&rsquo;t have to be as draconian as it sounds though. You could relax this approach and commit to having each level preallocated and never having dynamic memory allocations while the game is running. That still allows you to dynamically allocate the memory needed for each level and keep wasted space to a minimum. Or you can take it even further and preallocate the contents of memory blocks that are streamed in memory. That way each block can be divided in the best way for that content and wasted space is kept to a minimum.</p>
<h4 id="reuse-recyclem">Reuse, RecycleM</h4>
<p>If you don&rsquo;t want to preallocate every single object you&rsquo;ll ever use, then you can create a smaller set, and reuse them as needed. This can be a bit tricky though. First of all, it needs to be very much specific to the type of object that is reused. So particles are easy to reuse (just drop the oldest one, or the ones not in view), but might be harder with enemy units or active projectiles. It&rsquo;s going to take some game knowledge of those objects to decide which ones to reuse and how to do it.</p>
<p>It also means that systems need to be prepared to either fail an allocation (if your current set of objects is full and you don&rsquo;t want to reuse an existing one), or they need to cope with an object disappearing from one frame to another. That&rsquo;s a relatively easy problem to solve by using handles or other weak references instead of direct pointers.</p>
<p>Then there&rsquo;s the issue that reusing an object isn&rsquo;t as simple as constructing a new one. You really need to make sure that when you reuse it, there&rsquo;s nothing left from the object it replaced. This is easy when your objects are just plain data in a table, but can be more complicated when they&rsquo;re complex C++ classes tied together with pointers. In any case, you can&rsquo;t apply the Resource Acquisition Is Initialization (RAII) pattern, but it doesn&rsquo;t seem to be a pattern very well suited for games, and it&rsquo;s a small price to pay for the simplicity that preallocation provides.</p>
<h3 id="specialized-heaps">Specialized Heaps</h3>
<p>Truth be told, a pure pre-allocated approach can be hard to pull off, especially with highly dynamic environments or games with user-created content. Specialized heaps is a combination of dynamic memory allocation and pre-allocation that takes the best of both worlds.</p>
<p>The idea behind specialized heaps is that the heaps themselves are pre-allocated, but they allow some form of specialized dynamic allocation within them. That way you avoid the problems of running out of memory, or memory fragmentation globally, but you still can perform some sort of dynamic allocation when needed.</p>
<p>One type of specialized heaps is based on the object type. If you can guarantee that all objects allocated in that heap are going to be of the same size, or at least a multiple of a certain size, memory management becomes much easier and less error prone, and removes a lot of the complexity of a general memory manager.</p>
<p>My favorite approach for games is to create specialized heaps based on the lifetime of the objects allocated in them. These heaps use sequential allocators, always allocating memory from the beginning of a memory block. When the lifetime of the objects is up, the heap is reset and allocations can start from the beginning again. The use of a simple sequential allocator bypasses all the insidious problems of general memory management: fragmentation, compaction, leaks, etc. See the code in <a href="http://gdmag.com/resources/code.htm">http://gdmag.com/resources/code.htm</a> for an implementation of a SequentialAllocator class.</p>
<p>The heap types most often used in games are:</p>
<ul>
<li>Level heap. Here you allocate all the assets and data for the level at load time. When the level is unloaded, all objects are destroyed at once. If your game makes heavy use of streaming, this can be a streaming block instead of a full level.</li>
<li>Frame heap. Any temporary objects that only need to last a frame or less get allocated here, and destroyed at the end of the frame.</li>
<li>Stack heap. This one is a bit different from the others. Like the other heaps, it uses a sequential allocator and objects are allocated from the beginning, but instead of destroying all objects at once, it only destroys objects up to the marker that is popped fro the stack.</li>
</ul>
<h3 id="what-about-tools">What About Tools?</h3>
<p>You can take everything I&rsquo;ve written here, and (almost) completely ignore it for tools. I fall in the camp of the programmers who consider the runtime as a totally separate beast from the tools. That means that the runtime can be lean and mean and minimalistic, but I can relax and use whatever technique makes me more productive when writing tools. That means you can allocate memory any time you want, you can use complex libraries like STL and Boost, etc. Most tools are going to run on a beefy PC and a few extra allocations here and there won&rsquo;t make any difference.</p>
<p>Be careful with performance-sensitive tools though. Tools that build assets or compute complex lighting calculations might be a bottleneck in the build process. In that case, performance becomes crucial again and you might want to be a bit more careful about memory layout and cache coherency.</p>
<p>On the other hand, if the tool you&rsquo;re writing is not performance sensitive, you should ask yourself if it really needs to be written in C++. Maybe C# or Python are better languages if all you&rsquo;re doing is transforming XML files or verifying that a file format is correct. Trading performance for ease of development is almost always a win with development tools.</p>
<p>Next time you reach out for a malloc inside your main loop, think about how it can fail. Maybe you can pre-allocate that memory and stop worrying about what&rsquo;s going to happen the day you prepare the release candidate.</p>
<p><em>This article was originally printed in the February 2009 issue of <a href="http://gdmag.com">Game Developer</a>.</em></p>
]]></content:encoded></item><item><title>The Const Nazi</title><link>https://gamesfromwithin.com/the-const-nazi/</link><pubDate>Thu, 15 Jul 2010 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/the-const-nazi/</guid><description>&lt;p&gt;Anybody who worked with me or saw any of my code, would know right away why they call me the Const Nazi. That&amp;rsquo;s because in my coding style, I make use of the keyword &lt;em&gt;const&lt;/em&gt; everywhere. But instead of going on about how &lt;em&gt;const&lt;/em&gt; is so great, I&amp;rsquo;m going to let Hitler tell us how he really feels about it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;No Flash? Try the &lt;a href="https://gamesfromwithin.com/wp-content/uploads/2010/07/const_nazi.mov"&gt;QuickTime video version&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Let me get one thing out of the way to stop all the trigger-happy, const-bashing, would-be-commenters: &lt;em&gt;const&lt;/em&gt; doesn&amp;rsquo;t make any guarantees that values don&amp;rsquo;t change.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Anybody who worked with me or saw any of my code, would know right away why they call me the Const Nazi. That&rsquo;s because in my coding style, I make use of the keyword <em>const</em> everywhere. But instead of going on about how <em>const</em> is so great, I&rsquo;m going to let Hitler tell us how he really feels about it.</p>
<p><em>No Flash? Try the <a href="/wp-content/uploads/2010/07/const_nazi.mov">QuickTime video version</a>.</em></p>
<p>Let me get one thing out of the way to stop all the trigger-happy, const-bashing, would-be-commenters: <em>const</em> doesn&rsquo;t make any guarantees that values don&rsquo;t change.</p>
<p>You can change a <em>const</em> variable by casting the constness away, or referencing it through a pointer, but you really had to go out of your way to do that. If it helped with that, const would solve (or improve) the memory aliasing problem like Hitler pointed out. It doesn&rsquo;t, so const is pretty weak as far as promises go. It just says &ldquo;I, the programmer, promise not to change this value on purpose (unless I&rsquo;m truly desperate)&rdquo;. Still, even a promise like that goes a long way helping with readability and maintenance.</p>
<p>With that out of the way, what exactly do I mean by using <em>const</em> everywhere?</p>
<h3 id="const-non-value-function-parameters">Const non-value function parameters</h3>
<p>Any reference or pointer function parameters that are pointing to data that will not be modified by the function should be declared as <em>const</em>. If you&rsquo;re going to use <em>const</em> just for one thing, this is the one to use. It&rsquo;s invaluable glancing at a function signature and seeing which parameters are inputs and which ones are outputs.</p>
<pre tabindex="0"><code>void Detach(PhysicsObject&amp; physObj, int attachmentIndex, const HandleManager&amp; mgr);
</code></pre><p>Marking those parameters as <em>const</em> also serves as a warning sign in case a programmer in the future tries to modify one of them. Imagine the disaster if the calling code assumes data never changes, but the function suddenly starts modifying that data! <em>const</em> won&rsquo;t prevent that from happening, but will remind the programmer that he&rsquo;s changing the &ldquo;contract&rdquo; and needs to revisit all calling code and check assumptions.</p>
<h3 id="const-local-variables">Const local variables</h3>
<p>This is a very important use of <em>const</em> and one of the ones hardly anyone follows. If I declare a local (stack) variable and its value never changes after initialization, I always declare it <em>const</em>. That way, whenever I see that variable used later in the code, I know that its value hasn&rsquo;t changed.</p>
<pre tabindex="0"><code>const Vec2 newPos = AttachmentUtils::ApplySnap(physObj, unsnappedPos);
const Vec2 deltaPos = newPos - physObj.center;
physObj.center = newPos;
</code></pre><p>This is one of the reasons why I did a 180 on the ternary C operator (?). I used to hate it and find it cryptic and unreadable, but now I find it compact and elegant and it fulfills my <em>const</em> fetish very well.</p>
<p>Imagine you have a function that is going to work in one of two objects and you need to compute the index to the object to work on. You could do it this way:</p>
<pre tabindex="0"><code>int index;
if (some condition)
	index = 0;
else
	index = 2;

DoSomethingWithIndex();
</code></pre><p>Not only does that take several lines not to do much, but index isn&rsquo;t <em>const</em> (argh!). So every time I see index anywhere later on in that function, I&rsquo;m going to have to spend the extra mental power to make sure nothing has changed (and, with my current coding style, I would assume it has changed).</p>
<p>Instead, we can simply do this:</p>
<pre tabindex="0"><code>const int index = (some condition) ? 0 : 2;
DoSomethingWithIndex();
</code></pre><p>Ahhhh&hellip; So much better!</p>
<h3 id="const-member-variables">Const member variables</h3>
<p>This one doesn&rsquo;t really apply to me anymore because I don&rsquo;t use classes and member variables. But if you do, I strongly encourage you do mark every possible member function as <em>const</em> whenever you can.</p>
<p>The only downside is that sometimes you&rsquo;ll have some internal bit of data that is really not changing the &ldquo;logical&rdquo; state of an object, but it&rsquo;s still modifying a variable (usually some caching or logging data). In that case, you&rsquo;ll have to resort to the mutable keyword.</p>
<h3 id="const-value-function-parameters">Const value function parameters</h3>
<p><img alt="const_nazi.jpg" loading="lazy" src="/the-const-nazi/images/const_nazi.jpg">Apparently I&rsquo;m not a total Const Nazi because this is one possible use of <em>const</em> that I choose to skip (even though I tried it for a while because of <a href="http://cnicholson.net/">Charles</a>).</p>
<p>Marking a value function parameter as <em>const</em> doesn&rsquo;t make any difference from the calling code point of view, but it serves the same purpose as marking local stack variables as <em>const</em> in the implementation of the function. You&rsquo;re just saying &ldquo;I&rsquo;m not going to modify that parameter in this function&rdquo; so it makes the code easier to understand.</p>
<p>I&rsquo;m actually all for this, but the only reason I&rsquo;m not doing it is because C/C++ makes it a pain. Marking parameters as <em>const</em> in the function declaration adds extra verbosity and doesn&rsquo;t help the person browsing the functions at all. You could actually put the <em>const</em> only in the function definition and it will work, but at that point the declaration and the definition are different, so you can&rsquo;t copy and paste them or use other automated tools or scripts.</p>
<p>The concept of <em>const</em> is one of the things I miss the most when programming other languages like C#. I don&rsquo;t understand why they didn&rsquo;t add it to the language. On something like Python or Perl I can understand because they&rsquo;re supposed to be so free form, but C#? (Edit: How about that? <a href="http://msdn.microsoft.com/en-us/library/e6w8fe1b(VS.71).aspx">Apparently C# has const</a>. It was either added in the last few years or I completely missed it before). It also really bugs me that Objective C or the Apple API doesn&rsquo;t make any use of <em>const</em>.</p>
<p>Frankly, if it were up to me, I would change the C/C++ language to make every variable <em>const</em> by default and adding the <em>nonconst</em> or <em>changeable</em> (or take over <em>mutable</em>) keyword for the ones you want to modify. It would make life much more pleasant.</p>
<p>But then again, that&rsquo;s why the call me the Const Nazi.</p>
<p><em>This post is part of <a href="http://idevblogaday.com/">iDevBlogADay</a>, a group of indie iPhone development blogs featuring two posts per day. You can keep up with iDevBlogADay through the <a href="http://idevblogaday.com/">web site</a>, <a href="http://feeds.feedburner.com/idevblogaday">RSS feed</a>, or <a href="http://twitter.com/#search?q=%23idevblogaday">Twitter</a>.</em></p>
]]></content:encoded></item><item><title>The Always-Evolving Coding Style</title><link>https://gamesfromwithin.com/the-always-evolving-coding-style/</link><pubDate>Fri, 25 Jun 2010 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/the-always-evolving-coding-style/</guid><description>&lt;p&gt;&lt;em&gt;This is my first entry into &lt;a href="http://twitter.com/#search?q=%23idevblogaday"&gt;#iDevBlogADay&lt;/a&gt;. It all &lt;a href="http://twitter.com/mysterycoconut/status/16871555420"&gt;started very innocently with a suggestion from Miguel&lt;/a&gt;, but the ball got rolling pretty quickly. The idea is to have one independent iPhone game developer write a blog entry each day of the week. At first we thought we would be hard-pressed to get 7 developers, but it&amp;rsquo;s starting to seem we might have multiples per day!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Check out the new sidebar with all the #iDevBlogADay blogs. We&amp;rsquo;re also putting together a &lt;a href="feed://pipes.yahoo.com/pipes/pipe.run?_id=52b65f0bbfca4cc92db78d0b0408cac6&amp;amp;_render=rss"&gt;common RSS feed&lt;/a&gt; if you want to subscribe to that instead.&lt;/p&gt;</description><content:encoded><![CDATA[<p><em>This is my first entry into <a href="http://twitter.com/#search?q=%23idevblogaday">#iDevBlogADay</a>. It all <a href="http://twitter.com/mysterycoconut/status/16871555420">started very innocently with a suggestion from Miguel</a>, but the ball got rolling pretty quickly. The idea is to have one independent iPhone game developer write a blog entry each day of the week. At first we thought we would be hard-pressed to get 7 developers, but it&rsquo;s starting to seem we might have multiples per day!</em></p>
<p>Check out the new sidebar with all the #iDevBlogADay blogs. We&rsquo;re also putting together a <a href="feed://pipes.yahoo.com/pipes/pipe.run?_id=52b65f0bbfca4cc92db78d0b0408cac6&amp;_render=rss">common RSS feed</a> if you want to subscribe to that instead.</p>
<p>Writing is addictive, so don&rsquo;t be surprised if this once-a-week minimum turns into multiple-times-a-week.</p>
<p> </p>
<p><img alt="matrix.jpg" loading="lazy" src="/the-always-evolving-coding-style/images/matrix.jpg">Every developer who&rsquo;s been working on a team for a while is able to tell the author of a piece of code just by looking at it. Sometimes it&rsquo;s even fun to do a forensic investigation and figure out not just the original author, but who else modified the source code afterwards.</p>
<p>What I find interesting is that I can do the same thing with my own code&hellip; as it changes over time. Every new language I learn, every book I read, every bit of code I see, every open-source project I browse, every pair-programming session, every conversation with a fellow developer leaves a mark behind. It slightly changes how I think of things, and realigns my values and priorities as a programmer. And those new values translate into different ways to write code, different architectures, and different coding styles.</p>
<p>It never happens overnight. I can&rsquo;t recall a single case where I changed my values in a short period of time, causing dramatic changes to my coding style. Instead, it&rsquo;s the accumulation of lots of little changes here and there that slowly shifts things around. It&rsquo;s like the movement of the Earth&rsquo;s magnetic pole: very slow, but changes radically over time (although maybe just a tad bit faster).</p>
<h3 id="why-talk-about-coding-styles">Why Talk About Coding Styles</h3>
<p>Coding style in itself is purely a personal thing, and therefore, very uninteresting to talk about. However, in its current form, my coding style goes against the grain of most general modern &ldquo;good practices&rdquo;. A few weeks ago I released <a href="/opengl-and-uikit-demo/">some sample source code</a> and it caused a bit of a stir because it was so unconventional. That&rsquo;s when I realized it might be worth talking about it after all (along with <a href="http://twitter.com/GeorgeSealy/status/15800523038">George bugging me about it</a>), and especially the reasons why it is the way it is.</p>
<p>Before I even start, I want to stress that I&rsquo;m not advocating this approach for everybody, and I&rsquo;m certainly not saying it&rsquo;s the perfect way to go. I know that in a couple of years from now, I&rsquo;ll look back at the code I&rsquo;m writing today and it will feel quaint and obsolete, just like the code I wrote during <a href="/office-tools-for-starving-startups/">Power of Two Games</a> looks today. All I&rsquo;m saying is that this is the style that fits <strong>me</strong> best <strong>today</strong>.</p>
<h3 id="motivation">Motivation</h3>
<p>This is my current situation which shapes my thinking and coding style:</p>
<ul>
<li>All my code is written in C and C++ (except for a bit of ObjC and assembly).</li>
<li>It&rsquo;s all for real-time games on iPhone, PCs, or modern consoles, so performance and resource management are very important.</li>
<li>I always try to write important code through <a href="/backwards-is-forward-making-better-games-with-test-driven-development/">Test-Driven Development</a>.</li>
<li>I&rsquo;m the only programmer (and only designer).</li>
<li>Build times in my codebase are very fast.</li>
</ul>
<p>And above all, <a href="/simple-is-beautiful/">I love simplicity</a>. I try to achieve simplicity by considering every bit of code and thinking whether it&rsquo;s absolutely necessary. I get rid of anything that&rsquo;s not essential, or that&rsquo;s not benefitting the project by at least two or three times as much as it&rsquo;s complicating it.</p>
<h3 id="how-i-write-today">How I Write Today</h3>
<p>So, what does my code look like these days? Something like this (this is taken from a prototype I wrote with <a href="http://twitter.com/mysterycoconut">Miguel</a> of <a href="http://mysterycoconut.com/">Mystery Coconut</a> fame):</p>
<pre tabindex="0"><code>namespace DiverMode
{
    enum Enum
    {
        Normal,
        Shocked,
        Inmune,
    };
}

struct DiverState
{
    DiverState()
        : mode(DiverMode::Normal)
        , pos(0,0)
        , dir(0)
        , o2(1)
        , boostTime(0)
        , timeLeftInShock(0)
        , timeLeftImmune(0)
    {}

    DiverMode::Enum mode;
    Vec2 pos;
    float dir;
    float o2;

    float boostTime;
    float timeLeftInShock;
    float timeLeftImmune;
};

namespace DiverUtils
{
    void Update(float dt, const Vec2&amp; tiltInput, GameState&amp; state);
    void Shock(DiverState&amp; diver);
    void StartSprint(DiverState&amp; diver);
    void StopSprint(DiverState&amp; diver);
}
</code></pre><p>The first thing that stands out is that I&rsquo;m using a struct and putting related functions in a namespace. It may seem that&rsquo;s just a convoluted way of writing a class with member functions, but there&rsquo;s more to it than that.</p>
<p>By keeping the data in a struct instead of a class, I&rsquo;m gaining several advantages:</p>
<ul>
<li>I&rsquo;m showing all the data there is and how big it is. Nothing is hidden.</li>
<li>I&rsquo;m making it clear that it&rsquo;s free of pointers and temporary variables.</li>
<li>I&rsquo;m allowing this data to be placed anywhere in memory.</li>
</ul>
<p>The fact that the functions are part of a namespace is not really defensible; it&rsquo;s pure personal preference. It would have been no different than if I had prefixed them with DriverUtils_ or anything else, I just think it looks clearner. I do prefer the functions to be separate and not member functions though. It makes it easier to organize functions that work on multiple bits of data at once. Otherwise you&rsquo;re stuck deciding whether to make them members of one structure or another. It also makes it easier to break up data structures into separate structures later on and minimize the amount of changes to the code.</p>
<p>Probably one of the biggest influences on me starting down this path was the famous article by Scott Meyers <a href="http://www.drdobbs.com/184401197;jsessionid=Z3IAXBFRBPX03QE1GHRSKHWATMY32JVN">How Non Member Functions Improve Encapsulation</a>. I remember being shocked the first time I read it (after having read religiously <a href="http://www.amazon.com/Effective-Specific-Improve-Programs-Designs/dp/0321334876/?tag=gamesfromwith-20">Effective C++</a> and <a href="http://www.amazon.com/More-Effective-Improve-Programs-Designs/dp/020163371X/?tag=gamesfromwith-20">More Effective C++</a>). That reasoning combined with all the other changes over the years, eventually led to my current approach.</p>
<p>Since everything is in a structure and everything is public, there&rsquo;s very little built-in defenses against misuse and screw-ups. That&rsquo;s fine because that&rsquo;s not a priority for me. Right now I&rsquo;m the only programmer, and if I work with someone else, I expect them to have a similar level of experience than me. Some codebases written with a defensive programming approach have an amazing amount of code (and therefore complexity) dedicated to babysitting programmers. No thanks. I do make extensive use of asserts and unit tests to allow me to quickly make large refactorings though.</p>
<p>Another thing to note that might not be immediately obvious from the example above is that all functions are very simple and shallow. They take a set of input parameters, and maybe an output parameter or just a return value. They simply transform the input data into the output data, without making extensive calls to other functions in turn. That&rsquo;s one of the basic approaches of <a href="/data-oriented-design/">data-oriented design</a>.</p>
<p>Because everything is laid out in memory in a very simple and clear way, it means that serialization is a piece of cake. I can fwrite and fread data and have instant, free serialization (you only need to do some extra work if you change formats and try to support older ones). Not only that, but it&rsquo;s great for saving the game state in memory and restoring it later (which I&rsquo;m using heavily in my current project). All it takes is this line of code:</p>
<pre tabindex="0"><code>oldGameState = currentGameState
</code></pre><p>This style is a dream come true for Test-Driven Development (TDD). No more worrying about mocks, and test injections, or anything like that. Give the function some input data, and see what the output is. Done! That simple.</p>
<p>One final aspect of this code that might be surprising to some is how concrete it is. This is not some generic game entity that hold some generic components, with connections defined in XML and bound together through templates. It&rsquo;s a dumb, <a href="http://en.wikipedia.org/wiki/Plain_old_data_structure">POD</a> Diver structure. Diver as in the guy going swimming underwater. This prototype had fish as well, and there was a Fish structure, and a large array of sequential, homogeneous Fish data. The main loop wasn&rsquo;t generic at all either: It was a sequence of UpdateDivers(), UpdateFish(), etc. Rendering was done in the same, explicit way, making it extra simple to minimize render calls and state changes. When you work with a system like this, you never, ever want to go back to a generic one where you have very little idea about the order in which things get updated or rendered.</p>
<h3 id="beyond-the-sample">Beyond The Sample</h3>
<p>To be fair, this sample code is very, very simple. The update function for a reasonable game element is probably larger than a few lines of code and will need to do a significant amount of work (check path nodes, cast rays, respond to collisions, etc). In that case, if it makes sense, the data contained in the structure can be split up. Or maybe the first update function generates some different output data that gets fed into later functions. For example, we can update all the different game entities, and as an output, get a list of ray cast operations they want to perform, do them all in a later step, and then feed the results back to the entities either later this frame or next frame if we don&rsquo;t mind the added latency.</p>
<p>There&rsquo;s also the question of code reuse. It&rsquo;s very easy to reuse some low level functions, but what happens when you want to apply the same operation to a Diver and to a Fish? Since they&rsquo;re not using inheritance, you can&rsquo;t use polymorphism. I&rsquo;ll cover that in a later blog post, but the quick preview is that you extract any common data that both structs have and work on that data in a homogeneous way.</p>
<p> </p>
<p>What do you think of this approach? In which ways do you think it falls short, and in which ways do you like it better than your current style?</p>
]]></content:encoded></item><item><title>Great Presentation on Data-Oriented Design</title><link>https://gamesfromwithin.com/great-presentation-on-data-oriented-design/</link><pubDate>Sun, 20 Dec 2009 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/great-presentation-on-data-oriented-design/</guid><description>&lt;p&gt;&lt;img alt="Memory CPU gap" loading="lazy" src="https://gamesfromwithin.com/great-presentation-on-data-oriented-design/images/mem_cpu_gap.jpg" title="Memory CPU gap"&gt;A few days ago, &lt;a href="http://twitter.com/TonyAlbrecht"&gt;Tony Albrecht&lt;/a&gt; posted the slides of his presentation titled &lt;a href="http://research.scee.net/files/presentations/gcapaustralia09/Pitfalls_of_Object_Oriented_Programming_GCAP_09.pdf"&gt;&amp;ldquo;Pitfalls of Object-Oriented Design&amp;rdquo;&lt;/a&gt; &lt;a href="#1"&gt;[1]&lt;/a&gt;. Even though the title is really broad and could easily be &lt;a href="http://www.reddit.com/r/programming/comments/ag43j/pitfalls_of_object_oriented_programming_pdf/"&gt;misinterpreted&lt;/a&gt;, it&amp;rsquo;s not just a general bash on OOD. Instead, it&amp;rsquo;s very much focused on how object-oriented design is not a good match for high-performance apps (games) on modern hardware architectures with slow memory access and deep memory hierarchies. His proposed solution: Data-oriented design.Â Spot on!&lt;/p&gt;</description><content:encoded><![CDATA[<p><img alt="Memory CPU gap" loading="lazy" src="/great-presentation-on-data-oriented-design/images/mem_cpu_gap.jpg" title="Memory CPU gap">A few days ago, <a href="http://twitter.com/TonyAlbrecht">Tony Albrecht</a> posted the slides of his presentation titled <a href="http://research.scee.net/files/presentations/gcapaustralia09/Pitfalls_of_Object_Oriented_Programming_GCAP_09.pdf">&ldquo;Pitfalls of Object-Oriented Design&rdquo;</a> <a href="#1">[1]</a>. Even though the title is really broad and could easily be <a href="http://www.reddit.com/r/programming/comments/ag43j/pitfalls_of_object_oriented_programming_pdf/">misinterpreted</a>, it&rsquo;s not just a general bash on OOD. Instead, it&rsquo;s very much focused on how object-oriented design is not a good match for high-performance apps (games) on modern hardware architectures with slow memory access and deep memory hierarchies. His proposed solution: Data-oriented design.Â Spot on!</p>
<p>If you haven&rsquo;t seen the presentation, go download it right now. It&rsquo;s really well put together and he has some great detailed examples on how caches are affected with traditional object-oriented design vs. a more data-oriented approach.</p>
<p>[1] Thanks to <a href="http://twitter.com/ChristerEricson/status/6783005918">Christer Ericson</a> for pointing that out.</p>
]]></content:encoded></item><item><title>Data-Oriented Design (Or Why You Might Be Shooting Yourself in The Foot With OOP)</title><link>https://gamesfromwithin.com/data-oriented-design/</link><pubDate>Fri, 04 Dec 2009 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/data-oriented-design/</guid><description>&lt;p&gt;Picture this: Toward the end of the development cycle, your game crawls, but you don&amp;rsquo;t see any obvious hotspots in the profiler. The culprit? Random memory access patterns and constant cache misses. In an attempt to improve performance, you try to parallelize parts of the code, but it takes heroic efforts, and, in the end, you barely get much of a speed-up due to all the synchronization you had to add. To top it off, the code is so complex that fixing bugs creates more problems, and the thought of adding new features is discarded right away. Sound familiar?&lt;/p&gt;</description><content:encoded><![CDATA[<p>Picture this: Toward the end of the development cycle, your game crawls, but you don&rsquo;t see any obvious hotspots in the profiler. The culprit? Random memory access patterns and constant cache misses. In an attempt to improve performance, you try to parallelize parts of the code, but it takes heroic efforts, and, in the end, you barely get much of a speed-up due to all the synchronization you had to add. To top it off, the code is so complex that fixing bugs creates more problems, and the thought of adding new features is discarded right away. Sound familiar?</p>
<p>That scenario pretty accurately describes almost every game I&rsquo;ve been involved with for the last 10 years. The reasons aren&rsquo;t the programming languages we&rsquo;re using, nor the development tools, nor even a lack of discipline. In my experience, it&rsquo;s object- oriented programming (OOP) and the culture that surrounds it that is in large part to blame for those problems. OOP could be hindering your project rather than helping it!</p>
<p>It&rsquo;s All About Data</p>
<p>OOP is so ingrained in the current game development culture that it&rsquo;s hard to think beyond objects when thinking about a game. After all, we&rsquo;ve been creating classes representing vehicles, players, and state machines for many years. What are the alternatives? Procedural programming? Functional languages? Exotic programming languages?</p>
<p>Data-oriented design is a different way to approach program design that addresses all these problems. Procedural programming focuses on procedure calls as its main element, and OOP deals primarily with objects. Notice that the main focus of both approaches is code: plain procedures (or functions) in one case, and grouped code associated with some internal state in the other. Data-oriented design shifts the perspective of programming from objects to the data itself: The type of the data, how it is laid out in memory, and how it will be read and processed in the game.</p>
<p>Programming, by definition, is about transforming data: It&rsquo;s the act of creating a sequence of machine instructions describing how to process the input data and create some specific output data. A game is nothing more than a program that works at interactive rates, so wouldn&rsquo;t it make sense for us to concentrate primarily on that data instead of on the code that manipulates it?</p>
<p>I&rsquo;d like to clear up potential confusion and stress that data-oriented design does not imply that something is data- driven. A data-driven game is usually a game that exposes a large amount of functionality outside of code and lets the data determine the behavior of the game. That is an orthogonal concept to data-oriented design, and can be used with any type of programming approach.</p>
<p>Ideal Data</p>
<p>If we look at a program from the data point of view, what does the ideal data look like? It depends on the data and how it&rsquo;s used. In general, the ideal data is in a format that we can use with the least amount of effort. In the best case, the format will be the same we expect as an output, so the processing is limited to just copying that data. Very often, our ideal data layout will be large blocks of contiguous, homogeneous data that we can process sequentially. In any case, the goal is to minimize the amount of transformations, and whenever possible, you should bake your data into this ideal format offline, during your asset-building process.</p>
<p>Because data-oriented design puts data first and foremost, we can architect our whole program around the ideal data format. We won&rsquo;t always be able to make it exactly ideal (the same way that code is hardly ever by-the-book OOP), but it&rsquo;s the primary goal to keep in mind. Once we achieve that, most of the problems I mentioned at the beginning of the column tend to melt away (more about that in the next section).</p>
<p>When we think about objects, we immediately think of treesâ€” inheritance trees, containment trees, or message-passing trees, and our data is naturally arranged that way. As a result, when we perform an operation on an object, it will usually result in that object in turn accessing other objects further down in the tree. Iterating over a set of objects performing the same operation generates cascading, totally different operations at each object (see Figure 1a).</p>
<p>To achieve the best possible data layout, it&rsquo;s helpful to break down each object into the different components, and group components of the same type together in memory, regardless of what object they came from. This organization results in large blocks of homogeneous data, which allow us to process the data sequentially (see Figure 1b). A key reason why data-oriented design is so powerful is because it works very well on large groups of objects. OOP, by definition, works on a single object. Step back for a minute and think of the last game you worked on: How many places in the code did you have only one of something? One enemy? One vehicle? One pathfinding node? One bullet? One particle? Never! Where there&rsquo;s one, there are many. OOP ignores that and deals with each object in isolation. Instead, we can make things easy for us and for the hardware and organize our data to deal with the common case of having many items of the same type.</p>
<p>Does this sound like a strange approach? Guess what? You&rsquo;re probably already doing this in some parts of your code: The particle system! Data-oriented design is turning our whole codebase into a gigantic particle system. Perhaps a name for this approach that would be more familiar to game programmers would have been particle-driven programming.</p>
<p>Advantages of Data-Oriented Design</p>
<p>hinking about data first and architecting the program based on that brings along lots of advantages.</p>
<p>Parallelization.</p>
<p>These days, there&rsquo;s no way around the fact that we need to deal with multiple cores. Anyone who has tried taking some OOP code and parallelizing it can attest how difficult, error prone, and possibly not very efficient that is. Often you end up adding lots of synchronization primitives to prevent concurrent access to data from multiple threads, and usually a lot of the threads end up idling for quite a while waiting for other threads to complete. As a result, the performance improvement can be quite underwhelming.</p>
<p>When we apply data-oriented design, parallelization becomes a lot simpler: We have the input data, a small function to process it, and some output data. We can easily take something like that and split it among multiple threads with minimal synchronization between them. We can even take it further and run that code on processors with local memory (like the SPUs on the Cell processor) without having to do anything differently.</p>
<p>Cache utilization.</p>
<p>In addition to using multiple cores, one of the keys to achieving great performance in modern hardware, with its deep instruction pipelines and slow memory systems with multiple levels of caches, is having cache-friendly memory access. Data-oriented design results in very efficient use of the instruction cache because the same code is executed over and over. Also, if we lay out the data in large, contiguous blocks, we can process the data sequentially, getting nearly perfect data cache usage and great performance. Possible optimizations. When we think of objects or functions, we tend to get stuck optimizing at the function or even the algorithm level; Reordering some function calls, changing the sort method, or even re-writing some C code with assembly.</p>
<p>That kind of optimization is certainly beneficial, but by thinking about the data first we can step further back and make larger, more important optimizations. Remember that all a game does is transform some data (assets, inputs, state) into some other data (graphics commands, new game states). By keeping in mind that flow of data, we can make higher-level, more intelligent decisions based on how the data is transformed, and how it is used. That kind of optimization can be extremely difficult and time- consuming to implement with more traditional OOP methods.</p>
<p>Modularity.</p>
<p>So far, all the advantages of data-oriented design have been based around performance: cache utilization, optimizations, and parallelization. There is no doubt that as game programmers, performance is an extremely important goal for us. There is often a conflict between techniques that improve performance and techniques that help readability and ease of development. For example, re-writing some code in assembly language can result in a performance boost, but usually makes the code harder to read and maintain.</p>
<p>Fortunately, data-oriented design is beneficial to both performance and ease of development. When you write code specifically to transform data, you end up with small functions, with very few dependencies on other parts of the code. The codebase ends up being very â€œflat,â€ with lots of leaf functions without many dependencies. This level of modularity and lack of dependences makes understanding, replacing, and updating the code much easier.</p>
<p>Testing.</p>
<p>The last major advantage of data-oriented design is ease of testing. As we saw in the June and August Inner Product columns, writing unit tests to check object interactions is not trivial. You need to set up mocks and test things indirectly. Frankly, it&rsquo;s a bit of a pain. On the other hand, when dealing directly with data, it couldn&rsquo;t be easier to write unit tests: Create some input data, call the transform function, and check that the output data is what we expect. There&rsquo;s nothing else to it. This is actually a huge advantage and makes code extremely easy to test, whether you&rsquo;re doing test-driven development or just writing unit tests after the code.</p>
<p>Drawbacks of Data-Oriented Design</p>
<p>Data-oriented design is not the silver bullet to all the problems in game development. It does help tremendously writing high-performance code and making programs more readable and easier to maintain, but it does come with a few drawbacks of its own.</p>
<p>The main problem with data-oriented design is that it&rsquo;s different from what most programmers are used to or learned in school. It requires turning our mental model of the program ninety degrees and changing how we think about it. It takes some practice before it becomes second-nature.</p>
<p>Also, because it&rsquo;s a different approach, it can be challenging to interface with existing code, written in a more OOP or procedural way. It&rsquo;s hard to write a single function in isolation, but as long as you can apply data-oriented design to a whole subsystem you should be able to reap a lot of the benefits.</p>
<p>Applying Data-Oriented Design</p>
<p>Enough of the theory and overview. How do you actually get started with data-oriented design? To start with, just pick a specific area in your code: navigation, animations, collisions, or something else. Later on, when most of your game engine is centered around the data, you can worry about data flow all the way from the start of a frame until the end.</p>
<p>The next step is to clearly identify the data inputs required by the system, and what kind of data it needs to generate. It&rsquo;s OK to think about it in OOP terms for now, just to help us identify the data. For example, in an animation system, some of the input data is skeletons, base poses, animation data, and current state. The result is not â€œthe code plays animations,â€ but the data generated by the animations that are currently playing. In this case, our outputs would be a new set of poses and an updated state.</p>
<p>It&rsquo;s important to take a step further and classify the input data based on how it is used. Is it read- only, read-write, or write-only? That classification will help guide design decisions about where to store it, and when to process it depending on dependencies with other parts of the program.</p>
<p>At this point, stop thinking of the data required for a single operation, and think in terms of applying it to dozens or hundreds of entries. We no longer have one skeleton, one base pose, and a current state, and instead we have a block of each of those types with many instances in each of the blocks.</p>
<p>Think very carefully how the data is used during the transformation process from input to output. You might realize that you need to scan a particular field in a structure to perform a pass on the data, and then you need to use the results to do another pass. In that case, it might make more sense to split that initial field into a separate block of memory that can be processed independently, allowing for better cache utilization and potential parallelization. Or maybe you need to vectorize some part of the code, which requires fetching data from different locations to put it in the same vector register. In that case, that data can be stored contiguously so vector operations can be applied directly, without any extra transformations.</p>
<p>Now you should have a very good understanding of your data. Writing the code to transform it is going to be much simpler. It&rsquo;s like writing code by filling in the blanks. You&rsquo;ll even be pleasantly surprised to realize that the code is much simpler and smaller than you thought in the first place, compared to what the equivalent OOP code would have been.</p>
<p>If you think back about most of the topics we&rsquo;ve covered in this column over the last year, you&rsquo;ll see that they were all leading toward this type of design. Now it&rsquo;s the time to be careful about how the data is aligned (Dec 2008 and Jan 2009), to bake data directly into an input format that you can use efficiently (Oct and Nov 2008), or to use non- pointer references between data blocks so they can be easily relocated (Sept 2009).</p>
<p>Is Thre Room For OOP?</p>
<p>Does this mean that OOP is useless and you should never apply it in your programs? I&rsquo;m not quite ready to say that. Thinking in terms of objects is not detrimental when there is only one of each object (a graphics device, a log manager, etc) although in that case you might as well write it with simpler C-style functions and file-level static data. Even in that situation, it&rsquo;s still important that those objects are designed around transforming data.</p>
<p>Another situation where I still find myself using OOP is GUI systems. Maybe it&rsquo;s because you&rsquo;re working with a system that is already designed in an object-oriented way, or maybe it&rsquo;s because performance and complexity are not crucial factors with GUI code. In any case, I much prefer GUI APIs that are light on inheritance and use containment as much as possible (Cocoa and CocoaTouch are good examples of this). It&rsquo;s very possible that a data-oriented GUI system could be written for games that would be a pleasure to work with, but I haven&rsquo;t seen one yet.</p>
<p>Finally, there&rsquo;s nothing stopping you from still having a mental picture of objects if that&rsquo;s the way you like to think about the game. It&rsquo;s just that the enemy entity won&rsquo;t be all in the same physical location in memory. Instead, it will be split up into smaller subcomponents, each one forming part of a larger data table of similar components.</p>
<p>Data-oriented design is a bit of a departure from traditional programming approaches, but by always thinking about the data and how it needs to be transformed, you&rsquo;ll be able to reap huge benefits both in terms of performance and ease of development.</p>
<p>Thanks to Mike Acton and Jim Tilander for challenging my ideas over the years and for their feedback on this article.</p>
<p>Picture this: Toward the end of the development cycle, your game crawls, but you don&rsquo;t see any obvious hotspots in the profiler. The culprit? Random memory access patterns and constant cache misses. In an attempt to improve performance, you try to parallelize parts of the code, but it takes heroic efforts, and, in the end, you barely get much of a speed-up due to all the synchronization you had to add. To top it off, the code is so complex that fixing bugs creates more problems, and the thought of adding new features is discarded right away. Sound familiar?</p>
<p>That scenario pretty accurately describes almost every game I&rsquo;ve been involved with for the last 10 years. The reasons aren&rsquo;t the programming languages we&rsquo;re using, nor the development tools, nor even a lack of discipline. In my experience, it&rsquo;s object- oriented programming (OOP) and the culture that surrounds it that is in large part to blame for those problems. OOP could be hindering your project rather than helping it!</p>
<h2 id="its-all-about-data">It&rsquo;s All About Data</h2>
<p>OOP is so ingrained in the current game development culture that it&rsquo;s hard to think beyond objects when thinking about a game. After all, we&rsquo;ve been creating classes representing vehicles, players, and state machines for many years. What are the alternatives? Procedural programming? Functional languages? Exotic programming languages?</p>
<p>Data-oriented design is a different way to approach program design that addresses all these problems. Procedural programming focuses on procedure calls as its main element, and OOP deals primarily with objects. Notice that the main focus of both approaches is code: plain procedures (or functions) in one case, and grouped code associated with some internal state in the other. Data-oriented design shifts the perspective of programming from objects to the data itself: The type of the data, how it is laid out in memory, and how it will be read and processed in the game.</p>
<p>Programming, by definition, is about transforming data: It&rsquo;s the act of creating a sequence of machine instructions describing how to process the input data and create some specific output data. A game is nothing more than a program that works at interactive rates, so wouldn&rsquo;t it make sense for us to concentrate primarily on that data instead of on the code that manipulates it?</p>
<p>I&rsquo;d like to clear up potential confusion and stress that data-oriented design does not imply that something is data- driven. A data-driven game is usually a game that exposes a large amount of functionality outside of code and lets the data determine the behavior of the game. That is an orthogonal concept to data-oriented design, and can be used with any type of programming approach.</p>
<h2 id="ideal-data">Ideal Data</h2>
<p><img alt="Call sequence with an object-oriented approach" loading="lazy" src="/data-oriented-design/images/oo_design.png" title="oo_design"></p>
<p><em>Figure 1a. Call sequence with an object-oriented approach</em></p>
<p>If we look at a program from the data point of view, what does the ideal data look like? It depends on the data and how it&rsquo;s used. In general, the ideal data is in a format that we can use with the least amount of effort. In the best case, the format will be the same we expect as an output, so the processing is limited to just copying that data. Very often, our ideal data layout will be large blocks of contiguous, homogeneous data that we can process sequentially. In any case, the goal is to minimize the amount of transformations, and whenever possible, you should bake your data into this ideal format offline, during your asset-building process.</p>
<p>Because data-oriented design puts data first and foremost, we can architect our whole program around the ideal data format. We won&rsquo;t always be able to make it exactly ideal (the same way that code is hardly ever by-the-book OOP), but it&rsquo;s the primary goal to keep in mind. Once we achieve that, most of the problems I mentioned at the beginning of the column tend to melt away (more about that in the next section).</p>
<p>When we think about objects, we immediately think of treesâ€” inheritance trees, containment trees, or message-passing trees, and our data is naturally arranged that way. As a result, when we perform an operation on an object, it will usually result in that object in turn accessing other objects further down in the tree. Iterating over a set of objects performing the same operation generates cascading, totally different operations at each object (see Figure 1a).</p>
<p><img alt="Call sequence with a data-oriented approach" loading="lazy" src="/data-oriented-design/images/do_design1.png" title="do_design"></p>
<p><em>Figure 1b. Call sequence with a data-oriented approach</em></p>
<p>To achieve the best possible data layout, it&rsquo;s helpful to break down each object into the different components, and group components of the same type together in memory, regardless of what object they came from. This organization results in large blocks of homogeneous data, which allow us to process the data sequentially (see Figure 1b). A key reason why data-oriented design is so powerful is because it works very well on large groups of objects. OOP, by definition, works on a single object. Step back for a minute and think of the last game you worked on: How many places in the code did you have only one of something? One enemy? One vehicle? One pathfinding node? One bullet? One particle? Never! Where there&rsquo;s one, there are many. OOP ignores that and deals with each object in isolation. Instead, we can make things easy for us and for the hardware and organize our data to deal with the common case of having many items of the same type.</p>
<p>Does this sound like a strange approach? Guess what? You&rsquo;re probably already doing this in some parts of your code: The particle system! Data-oriented design is turning our whole codebase into a gigantic particle system. Perhaps a name for this approach that would be more familiar to game programmers would have been particle-driven programming.</p>
<h2 id="advantages-of-data-oriented-design">Advantages of Data-Oriented Design</h2>
<p>Thinking about data first and architecting the program based on that brings along lots of advantages.</p>
<h3 id="parallelization">Parallelization.</h3>
<p>These days, there&rsquo;s no way around the fact that we need to deal with multiple cores. Anyone who has tried taking some OOP code and parallelizing it can attest how difficult, error prone, and possibly not very efficient that is. Often you end up adding lots of synchronization primitives to prevent concurrent access to data from multiple threads, and usually a lot of the threads end up idling for quite a while waiting for other threads to complete. As a result, the performance improvement can be quite underwhelming.</p>
<p>When we apply data-oriented design, parallelization becomes a lot simpler: We have the input data, a small function to process it, and some output data. We can easily take something like that and split it among multiple threads with minimal synchronization between them. We can even take it further and run that code on processors with local memory (like the SPUs on the Cell processor) without having to do anything differently.</p>
<h3 id="cache-utilization">Cache utilization.</h3>
<p>In addition to using multiple cores, one of the keys to achieving great performance in modern hardware, with its deep instruction pipelines and slow memory systems with multiple levels of caches, is having cache-friendly memory access. Data-oriented design results in very efficient use of the instruction cache because the same code is executed over and over. Also, if we lay out the data in large, contiguous blocks, we can process the data sequentially, getting nearly perfect data cache usage and great performance. Possible optimizations. When we think of objects or functions, we tend to get stuck optimizing at the function or even the algorithm level; Reordering some function calls, changing the sort method, or even re-writing some C code with assembly.</p>
<p>That kind of optimization is certainly beneficial, but by thinking about the data first we can step further back and make larger, more important optimizations. Remember that all a game does is transform some data (assets, inputs, state) into some other data (graphics commands, new game states). By keeping in mind that flow of data, we can make higher-level, more intelligent decisions based on how the data is transformed, and how it is used. That kind of optimization can be extremely difficult and time- consuming to implement with more traditional OOP methods.</p>
<h3 id="modularity">Modularity.</h3>
<p>So far, all the advantages of data-oriented design have been based around performance: cache utilization, optimizations, and parallelization. There is no doubt that as game programmers, performance is an extremely important goal for us. There is often a conflict between techniques that improve performance and techniques that help readability and ease of development. For example, re-writing some code in assembly language can result in a performance boost, but usually makes the code harder to read and maintain.</p>
<p>Fortunately, data-oriented design is beneficial to both performance and ease of development. When you write code specifically to transform data, you end up with small functions, with very few dependencies on other parts of the code. The codebase ends up being very â€œflat,â€ with lots of leaf functions without many dependencies. This level of modularity and lack of dependences makes understanding, replacing, and updating the code much easier.</p>
<h3 id="testing">Testing.</h3>
<p>The last major advantage of data-oriented design is ease of testing. As we saw in the June and August Inner Product columns, writing unit tests to check object interactions is not trivial. You need to set up mocks and test things indirectly. Frankly, it&rsquo;s a bit of a pain. On the other hand, when dealing directly with data, it couldn&rsquo;t be easier to write unit tests: Create some input data, call the transform function, and check that the output data is what we expect. There&rsquo;s nothing else to it. This is actually a huge advantage and makes code extremely easy to test, whether you&rsquo;re doing test-driven development or just writing unit tests after the code.</p>
<h2 id="drawbacks-of-data-oriented-design">Drawbacks of Data-Oriented Design</h2>
<p>Data-oriented design is not the silver bullet to all the problems in game development. It does help tremendously writing high-performance code and making programs more readable and easier to maintain, but it does come with a few drawbacks of its own.</p>
<p>The main problem with data-oriented design is that it&rsquo;s different from what most programmers are used to or learned in school. It requires turning our mental model of the program ninety degrees and changing how we think about it. It takes some practice before it becomes second-nature.</p>
<p>Also, because it&rsquo;s a different approach, it can be challenging to interface with existing code, written in a more OOP or procedural way. It&rsquo;s hard to write a single function in isolation, but as long as you can apply data-oriented design to a whole subsystem you should be able to reap a lot of the benefits.</p>
<h2 id="applying-data-oriented-design">Applying Data-Oriented Design</h2>
<p>Enough of the theory and overview. How do you actually get started with data-oriented design? To start with, just pick a specific area in your code: navigation, animations, collisions, or something else. Later on, when most of your game engine is centered around the data, you can worry about data flow all the way from the start of a frame until the end.</p>
<p>The next step is to clearly identify the data inputs required by the system, and what kind of data it needs to generate. It&rsquo;s OK to think about it in OOP terms for now, just to help us identify the data. For example, in an animation system, some of the input data is skeletons, base poses, animation data, and current state. The result is not â€œthe code plays animations,â€ but the data generated by the animations that are currently playing. In this case, our outputs would be a new set of poses and an updated state.</p>
<p>It&rsquo;s important to take a step further and classify the input data based on how it is used. Is it read- only, read-write, or write-only? That classification will help guide design decisions about where to store it, and when to process it depending on dependencies with other parts of the program.</p>
<p>At this point, stop thinking of the data required for a single operation, and think in terms of applying it to dozens or hundreds of entries. We no longer have one skeleton, one base pose, and a current state, and instead we have a block of each of those types with many instances in each of the blocks.</p>
<p>Think very carefully how the data is used during the transformation process from input to output. You might realize that you need to scan a particular field in a structure to perform a pass on the data, and then you need to use the results to do another pass. In that case, it might make more sense to split that initial field into a separate block of memory that can be processed independently, allowing for better cache utilization and potential parallelization. Or maybe you need to vectorize some part of the code, which requires fetching data from different locations to put it in the same vector register. In that case, that data can be stored contiguously so vector operations can be applied directly, without any extra transformations.</p>
<p>Now you should have a very good understanding of your data. Writing the code to transform it is going to be much simpler. It&rsquo;s like writing code by filling in the blanks. You&rsquo;ll even be pleasantly surprised to realize that the code is much simpler and smaller than you thought in the first place, compared to what the equivalent OOP code would have been.</p>
<p>If you think back about most of the topics we&rsquo;ve covered in this column over the last year, you&rsquo;ll see that they were all leading toward this type of design. Now it&rsquo;s the time to be careful about how the data is aligned (Dec 2008 and Jan 2009), to bake data directly into an input format that you can use efficiently (Oct and Nov 2008), or to use non- pointer references between data blocks so they can be easily relocated (Sept 2009).</p>
<h2 id="is-there-room-for-oop">Is There Room For OOP?</h2>
<p>Does this mean that OOP is useless and you should never apply it in your programs? I&rsquo;m not quite ready to say that. Thinking in terms of objects is not detrimental when there is only one of each object (a graphics device, a log manager, etc) although in that case you might as well write it with simpler C-style functions and file-level static data. Even in that situation, it&rsquo;s still important that those objects are designed around transforming data.</p>
<p>Another situation where I still find myself using OOP is GUI systems. Maybe it&rsquo;s because you&rsquo;re working with a system that is already designed in an object-oriented way, or maybe it&rsquo;s because performance and complexity are not crucial factors with GUI code. In any case, I much prefer GUI APIs that are light on inheritance and use containment as much as possible (Cocoa and CocoaTouch are good examples of this). It&rsquo;s very possible that a data-oriented GUI system could be written for games that would be a pleasure to work with, but I haven&rsquo;t seen one yet.</p>
<p>Finally, there&rsquo;s nothing stopping you from still having a mental picture of objects if that&rsquo;s the way you like to think about the game. It&rsquo;s just that the enemy entity won&rsquo;t be all in the same physical location in memory. Instead, it will be split up into smaller subcomponents, each one forming part of a larger data table of similar components.</p>
<p>Data-oriented design is a bit of a departure from traditional programming approaches, but by always thinking about the data and how it needs to be transformed, you&rsquo;ll be able to reap huge benefits both in terms of performance and ease of development.</p>
<p>Thanks to <a href="http://www.cellperformance.com/mike_acton">Mike Acton</a> and <a href="http://www.tilander.org/aurora/">Jim Tilander</a> for challenging my ideas over the years and for their feedback on this article.</p>
<p>This article was originally printed in the September 2009 issue of <a href="http://gdmag.com">Game Developer</a>.</p>
<p><a href="http://www.lameproof.com/zboard/zboard.php?id=bbs2&amp;no=790">Here&rsquo;s a Korean translation of this article</a> byÂ Hakkyu Kim.</p>
]]></content:encoded></item><item><title>The Measure Of Code</title><link>https://gamesfromwithin.com/the-measure-of-code/</link><pubDate>Fri, 13 Jun 2008 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/the-measure-of-code/</guid><description>&lt;p&gt;I&amp;rsquo;ve gotten a lot of questions about how big our codebase is, how fast does it build, how many tests we have&amp;hellip; Fear not, Gentle Reader, all your burning questions will be answered here.&lt;/p&gt;</description><content:encoded><![CDATA[<p>I&rsquo;ve gotten a lot of questions about how big our codebase is, how fast does it build, how many tests we have&hellip; Fear not, Gentle Reader, all your burning questions will be answered here.</p>
<h2 id="size">Size</h2>
<p>Charles and I were priding ourselves in keeping things small and minimal. But truth be told, it&rsquo;s not like we were keeping track of how many lines of code we had written. Were things as small as we hoped they were?</p>
<p>The most convenient way of counting lines of code that I know is <a href="http://cloc.sourceforge.net/">CLOC</a>. It&rsquo;s an extremely easy to use open source program which counts the lines of code in a codebase, gives very detailed information, strips out whitespace, breaks things down by language, and does just about everything you&rsquo;d want from a program like that.</p>
<p>Running it on the latest version of our code (not including any 3rd party libraries) produces this:</p>
<pre tabindex="0"><code>Â Â Â  1621 text files.Â Â Â  1579 unique files.Â Â Â  3721 files ignored.
-------------------------------------------------------------------------------
LanguageÂ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â filesÂ Â Â Â Â Â Â Â Â  blankÂ Â Â Â Â Â Â  commentÂ Â Â Â Â Â Â Â Â Â code
-------------------------------------------------------------------------------
C++Â Â Â Â Â Â  Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 485Â Â Â Â Â Â Â Â Â  13577Â Â Â Â Â Â Â Â Â Â Â  303Â Â Â Â Â Â Â Â Â  46181
C#Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  324Â Â Â Â Â Â Â Â Â Â  4935Â Â Â Â Â Â Â Â Â Â Â  712Â Â Â Â Â Â Â Â Â  22966
C/C++ HeaderÂ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  407Â Â Â Â Â Â Â Â Â Â  4153Â Â Â Â Â Â Â Â Â Â Â Â  95Â Â Â Â Â Â Â Â Â  11975
MSBuild scriptsÂ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  18Â Â Â Â Â Â Â Â Â Â Â Â Â  0Â Â Â Â Â Â Â Â Â Â Â  126Â Â Â Â Â Â Â Â Â Â 1490
-------------------------------------------------------------------------------
SUM:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  1234Â Â Â Â Â Â Â Â Â  22665Â Â Â Â Â Â Â Â Â Â  1236Â Â Â Â Â Â Â Â Â  82612
</code></pre><p>Almost 60K lines of C++ code seemed very high. At first I thought it was because CLOC was counting files twice: once in their regular location and once in the .svn directory, but apparently it&rsquo;s already removing all duplicates, so that wasn&rsquo;t it.</p>
<p>Almost more scary than the amount of C++ code (which is all our runtime and some of our tools) is the amount of C# code. For a language that claims to be of significantly higher level than C++, that&rsquo;s quite a mouthful of code!</p>
<p>Another surprising count in there is the number of lines with comments. Since we make heavy use of <a href="http://www.gamesfromwithin.com/articles/cat_testdriven_development.html">TDD</a>, I really didn&rsquo;t expect more than a couple dozen lines of code in the whole codebase. Still, I&rsquo;m kind of proud that we have less than one line of code per file on average :-)</p>
<p>Here&rsquo;s a more detailed breakdown, with the line count just for our runtime (engine and game):</p>
<pre tabindex="0"><code>1089 text files.    1053 unique files.    2338 files ignored.
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
C++                            441          11997            245          40943
C/C++ Header                   385           3964             90          11405
-------------------------------------------------------------------------------
SUM:                           826          15961            335          52348
</code></pre><p>and for our tools:</p>
<pre tabindex="0"><code>532 text files.     531 unique files.    1383 files ignored.
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
C#                             324           4935            712          22966
C++                             44           1580             58           5238
MSBuild scripts                 18              0            126           1490
C/C++ Header                    23            199              5            591
-------------------------------------------------------------------------------
SUM:                           409           6714            901          30285
</code></pre><h2 id="tests">Tests</h2>
<p>Then I realized that a good chunk of those were tests. So excluding all directories matching *Tests* gets the following result:</p>
<pre tabindex="0"><code>1206 text files.    1187 unique files.    4199 files ignored.
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
C++                            283           6464            150          22464
C#                             213           2636            534          12402
C/C++ Header                   380           3824             94          10782
MSBuild scripts                 12              0             84            978
-------------------------------------------------------------------------------
SUM:                           888          12924            862          46626
</code></pre><p>A bit more than half the C++ code consisted of tests. That&rsquo;s pretty consistent with my experience with TDD. C# seems to follow a similar percentage as well.</p>
<p>As for the exact number of tests, running a grep for TEST shows all the C++ tests:</p>
<pre tabindex="0"><code>C:\pow2&gt;grep -r TEST SweetPea Engine Tools | grep -v svn | wcÂ Â  2163Â Â Â  3620Â  221953
</code></pre><p>And doing the same thing with [Test] brings up all C# tests:</p>
<pre tabindex="0"><code>C:\pow2&gt;grep -r \[Test\] SweetPea Engine Tools | grep -v svn | wcÂ Â  735Â Â Â  1470Â Â 52717
</code></pre><p>That means that our average C++ test is about 11.5 lines long, and C# tests 14.4. Frankly, that sounds rather high. We make heavy use of fixtures whenever possible and each test usually only checks for a single condition (even if it involves a couple check statements). I suppose that number is higher than expected because it probably includes all the lines from #include statements and all the fixtures as part of the average.</p>
<table>
	<thead>
			<tr>
					<th><strong>Language</strong></th>
					<th><strong>Lines</strong></th>
					<th><strong>Non test lines</strong></th>
					<th><strong>Test lines</strong></th>
					<th><strong>% of non test code</strong></th>
					<th><strong>Number of tests</strong></th>
					<th><strong>Lines per test</strong></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>C++</td>
					<td>58156</td>
					<td>33246</td>
					<td>24910</td>
					<td>57% *</td>
					<td>2163</td>
					<td>11.5</td>
			</tr>
			<tr>
					<td>C#</td>
					<td>22966</td>
					<td>12402</td>
					<td>10564</td>
					<td>54%</td>
					<td>735</td>
					<td>14.4</td>
			</tr>
	</tbody>
</table>
<p>* If we only count cpp files, that goes down to 49%</p>
<p>I was curious about that last part of checking a single thing per test, so I ran a grep for the number of CHECK statements in our code:</p>
<pre tabindex="0"><code>C:\pow2&gt;grep -r CHECK SweetPea Engine Tools | grep -v svn | wcÂ Â  3886Â Â  15079Â  399598
</code></pre><h2><img loading="lazy" src="images/tapemeasure.jpg"></h2>
<p>That&rsquo;s 1.8 CHECK statements per TEST, which is about right. Even though we&rsquo;re checking for a single condition, we&rsquo;ll often check a couple things about it (i.e. the camera stopped and it reached its final destination).</p>
<h2 id="build-times">Build Times</h2>
<p>So, given that amount of code, how long does it take to build it? Clearly it depends on your hardware. Since we&rsquo;re not exactly rolling in money, we don&rsquo;t have particularly powerful machines. Here at home, I&rsquo;m using a modest Core 2 Duo E4300 (overclocked to 2.6 GHz) with fast memory and a relatively fast SATA hard drive, so that&rsquo;s what I used for all my timings.</p>
<p>A full build of our game, plus all the libraries, all the tests, and running all the tests takes exactly 1 minute and 10 seconds. That&rsquo;s pretty good for two reasons:</p>
<ul>
<li>When we work with the game we don&rsquo;t build and run the unit tests for the engine. We have a separate solution for that. A full build of just the engine, the game, and the game unit tests only takes 43 seconds.</li>
<li>The game itself is a fairly large project and devenv doesn&rsquo;t know how to paralellize that build, so it&rsquo;s only using half the available CPU power for about half the build time.</li>
</ul>
<p>An incremental build after changing a single cpp file takes <a href="http://powerof2games.com/node/32">slightly over a second</a> (including half a second of unit test execution).</p>
<p>As you can imagine, working with that codebase is a dream come true. Snappy, responsive. Nothing is hard enough that can&rsquo;t be changed.</p>
<p>Unfortunately that&rsquo;s where the fairy tale ends. The tools are another story altogether. Our C# tools, with all their unit tests, build in a mere 18 seconds, and the C++ tools in 1 minute and 10 seconds. That&rsquo;s not too bad, except that it&rsquo;s a surprisingly large amount of time for the C++ tools since there aren&rsquo;t that many of them.</p>
<p>Here&rsquo;s the kicker, doing another build without changing a single thing take 38 seconds. Whoa! We&rsquo;re doing some C++/CLI trickery and apparently dependency checking is totally broken in VS2005 (either that, or we just don&rsquo;t know how to set it up right).</p>
<h2 id="keeping-things-fast">Keeping things fast</h2>
<p>What&rsquo;s the secret of a lighting-fast build? Clearly, keeping the code size down is crucial. If your codebase is 2 million lines of code, builds are going to be painful no matter what. But they can be a little less painful with some gentle care.</p>
<p>One of the main build-time killers that we&rsquo;re avoiding is the use of STL or <a href="http://www.boost.org/">Boost</a>. Those libraries pull in everything and the kitchen sink, and their heavy use of templates make build and link time go through the roof. No thanks.</p>
<p>Our template use is pretty minimal. We have a couple containers (which I love and I&rsquo;ll write about it one of these days) and that&rsquo;s about it.</p>
<p>We&rsquo;re pretty anal when it comes to keeping <a href="/physical-structure-and-c-part-2-build-times/%20">physical dependencies</a> to a minimum. We forward declare aggressively, and we only include the headers that are necessary for each cpp file (<a href="http://www.gimpel.com/">PC Lint</a> is &ldquo;kind&rdquo; of enough to remind us every time we have unnecessary #includes). We&rsquo;re not using external include guards or #pragma once.</p>
<p>Precompiled headers are either not used, or kept to a minimum. I think the only project that uses them is the game and only for Havok headers. We don&rsquo;t even have windows.h in a precompiled header (which would be a really bad idea because you&rsquo;d be putting all the junk in windows.h available to your whole program).</p>
<p>Finally, we are using incremental links whenever possible. I remember a few versions of Visual Studio ago they were pretty broken, but they&rsquo;re not giving us any problems. The only caveat is that if you modify a static library your program is linking with, it will force a full link. So they&rsquo;re really only good for modifying the executable itself.</p>
<p>We&rsquo;re not using any distributed builds. First of all, we don&rsquo;t have enough computers to make it worthwhile. And second, I had horrible experiences with distributed builds in the past. They would help with a badly structured codebase, at the cost of longer incremental builds and mysterious spurious bad builds. Besides, once they&rsquo;re in place, they tend to encourage even further disregard for keeping dependencies to a minimum.</p>
<h2 id="how-about-you">How about you?</h2>
<p>So, that&rsquo;s it for the Power of Two codebase. How about you? Want to share your size, build times, or any other data?</p>]]></content:encoded></item><item><title>What's Your Pain Threshold?</title><link>https://gamesfromwithin.com/whats-your-pain-threshold/</link><pubDate>Tue, 10 Jun 2008 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/whats-your-pain-threshold/</guid><description>&lt;p&gt;Mine is two seconds.&lt;/p&gt;
&lt;p&gt;Here at Power of Two Games, we write all our code with &lt;a href="https://gamesfromwithin.com/backwards-is-forward-making-better-games-with-test-driven-development/"&gt;test-driven development.&lt;/a&gt; C++ tests use the fantastic &lt;a href="http://unittest-cpp.sourceforge.net/"&gt;UnitTest++ framework&lt;/a&gt; (no big surprise there :-) ) and we run all unit tests automatically as the last step of our build process. That means that every time we build anything, the tests for that library or program get executed. Every time. No exceptions.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Mine is two seconds.</p>
<p>Here at Power of Two Games, we write all our code with <a href="/backwards-is-forward-making-better-games-with-test-driven-development/">test-driven development.</a> C++ tests use the fantastic <a href="http://unittest-cpp.sourceforge.net/">UnitTest++ framework</a> (no big surprise there :-) ) and we run all unit tests automatically as the last step of our build process. That means that every time we build anything, the tests for that library or program get executed. Every time. No exceptions.</p>
<p>None of that would be an issue except that TDD creates lots of unit tests and encourages almost constant incremental builds. In the past I&rsquo;ve stressed how important it is to keep them fast. But this week that I was able to really feel what a dramatic difference slow unit tests make.</p>
<p>For many months, our unit tests ran under one second. Each library has its own set of unit tests, and so does the game and each tool. So even though we were writing lots of unit tests, we weren&rsquo;t always running them all at the same time. There was a definite snappiness to coding: write test, compile, fail, write code, compile, pass, move on. Go, go, go.</p>
<p>As the game project got larger, we started accumulating more unit tests and testing times started creeping up into the second range. At the time, I couldn&rsquo;t quite put my finger on what had changed, but there was a definite change in feel. Things weren&rsquo;t quite as snappy.</p>
<p>Then, about a couple of weeks ago, we hit the two second mark and things definitely changed.</p>
<pre tabindex="0"><code>&gt; bin\SweetPea_d.exe -unittestSuccess: 1145 tests passed.Test time: 2.13 seconds.
</code></pre><p>As the tests were running, my mind would wander, thinking about what test I would write next, or whether the code I had just written would be cache-friendly, or whether we&rsquo;d do Honey&rsquo;s or Manhattan for lunch. I would be jerked out of my <a href="http://en.wikipedia.org/wiki/Flow_%28psychology%29">state of flow</a>. It wasn&rsquo;t just me, Charles felt it too. The difference in productivity was huge.</p>
<h2 id="the-zones">The Zones</h2>
<p>For those of you laughing at those times and dismissing them as insignificant, you need to keep in mind that our build times are very short:</p>
<ul>
<li>An incremental build with just a change in a cpp file takes under a second (including link times).</li>
<li>A full build of *all* our runtime code, including libraries, is around 50 seconds in a dual-core machine <a href="#note1">[1]</a>.</li>
</ul>
<p>So adding on 2 seconds to the incremental build time is going from â€œpractically instantâ€ to â€œOK, I&rsquo;m waiting&hellip;â€.<img loading="lazy" src="images/antique-clocks.jpg"></p>
<p>Of course, none of this has anything to do with unit tests in particular. It&rsquo;s total incremental build times (including compiling, linking, and running unit tests) that matter. An incremental build that takes 3 seconds with no unit tests is just as bad as one that is under one second with 3 second unit tests. They both interrupt the flow the same way.</p>
<p>I&rsquo;ve often thought about how a company size affects communication and â€œfeelâ€. It&rsquo;s close to a step function with logarithmic scale: there&rsquo;s a distinct jump from a company of 3 to a company of 10, to one of 35, to one of 100+.</p>
<p>I think something similar applies to build times <a href="#note2">[2]</a></p>
<ul>
<li>0 to 2 seconds. Programmer stays in the flow. Productivity is way high.</li>
<li>2 to 8 seconds. Flow is broken. Definite feel of things being a bit painful and sluggish.</li>
<li>8 to 30 seconds. Attention wanders to other parts of the code, email, etc. Multitasking kicks in and overall productivity plummets.</li>
<li>30+ seconds. Builds seen as batch processing. After each build is started, some other action is started. Maybe even physically get up, get a drink, start a conversation. Full brain reboot between coding tasks.</li>
<li>5+ minutes. Programmers bang their heads against the desk, actively consider the merits of different forms of suicide, or at the very least start polishing their resumes.</li>
</ul>
<h2 id="the-fix">The Fix</h2>
<p>Having been spoiled by sub-second build times, neither one of us wanted to put up with the broken flow of 2+ second builds, so we decided it was time to fix things <a href="#note3">[3]</a>.</p>
<p>The good news is that our slow build times were solely due to running the unit tests. 2.13 seconds to run only about 1100+ tests is really bad, even on a so-so desktop machine like the ones we can afford. That&rsquo;s almost 2ms per test! Remember that these are unit tests, not functional tests. So I expect to be able to run several thousands of these under one second. Something was way off.</p>
<p>Things had gotten much worse in the last couple of weeks, so it wasn&rsquo;t a slow, steady creep up. Chances are we had introduced something very slow recently, which meant it was probably easy to fix.</p>
<p>As a first pass, we turned on the option to fail any test that takes over a certain amount of time in UnitTest++:</p>
<pre tabindex="0"><code>RunAllTests(reporter, UnitTest::Test::GetTestList(), NULL, 5); // fail any test over 5ms
</code></pre><p>That brought about tons of failing test, most of them added recently and creating one particular object in their fixtures. Digging a big deeper, that particular class had an array of 25,000 (yes, that many zeros) objects. Those objects were <a href="http://en.wikipedia.org/wiki/Plain_Old_Data_Structures">plain-old-data structures</a>, but had a default constructor. Even though the constructor was simply initializing its members to zero, that was causing a significant slow down when so many objects were created. To make things worse, some of the code I had written was iterating over the array resetting the entries or shifting them up or down, repeatedly calling the constructor. Ouch!</p>
<p>A few minutes and lots of code hacking later, and the object didn&rsquo;t call a single constructor anymore. Our test times went down by almost half. Victory!</p>
<p>We were already at 1 second, which is in the acceptable range, but since we were here, maybe we could improve things a bit more. After all, 1ms per test is still too slow.</p>
<p>UnitTest++ wasn&rsquo;t reporting failing tests over 1ms very reliably. Different runs would cause very different results. Things were too spread out or other things in the computer were interfering too much.</p>
<p>About a fifth or so of our tests use Havok. Not with mocks, but directly. They each initialize Havok, create a world, and deal with a simple rigid body, constraint, or something of the sort. I suspected all along that the Havok system initialization and shutdown for each test was probably causing quite a slow down, so I changed it to be initialized only once before we ran any tests.</p>
<p>And that did the trick. With that change we were down to 0.16 seconds. Back to snappy, happy land!</p>
<pre tabindex="0"><code>&gt; bin\SweetPea_d.exe -unittestSuccess: 1145 tests passed.Test time: 0.16 seconds.
</code></pre><p>In release mode things are even better, but we do most development in debug mode, so that&rsquo;s the really important one:</p>
<pre tabindex="0"><code>&gt; bin\SweetPea.exe -unittestSuccess: 1145 tests passed.Test time: 0.06 seconds.
</code></pre><p>Perhaps sub-second build times are not realistic for all projects, but I think there&rsquo;s a lot to be gained by keeping compile, link, and test times as short as possible. For tips on how to keep compile times down, check out <a href="/physical-structure-and-c-part-1-a-first-look/%20">these articles</a> <a href="/physical-structure-and-c-part-2-build-times/%20">I wrote a while ago</a>. If your unit tests are slow and you really can&rsquo;t speed them up anymore, consider splitting them into two sets: one that is important or recent ones that runs with every build, and another, more comprehensive one that runs in the build server.</p>
<p>Even if you cut down from 20 seconds down to 10, you&rsquo;ll be making a huge shift in how you&rsquo;re able to work and iterate on your programming.</p>
<p>[1] We&rsquo;d love to keep detailed metrics with each build: executable size, number of lines of code, number of tests, etc, etc. Unfortunately, when the rubber hits the road, that ends up in the â€œnice to have categoryâ€ and we simply have no resources to spare on a two-man startup.</p>
<p>[2] For a whole whooping statistical population of one since I&rsquo;m only talking about my experience. Still, I suspect that the same applies to many other programmers by scaling the function by some constant.</p>
<p>[3] Perfect use of agile mentality. Fix things when you need them fixed, not before. But make sure you do fix them when you need them. Otherwise it&rsquo;s not agile, it&rsquo;s just lazy.</p>]]></content:encoded></item><item><title>Stupid C++ Tricks #2: Better Enums</title><link>https://gamesfromwithin.com/stupid-c-tricks-2-better-enums/</link><pubDate>Mon, 14 Apr 2008 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/stupid-c-tricks-2-better-enums/</guid><description>&lt;p&gt;So much for the new year&amp;rsquo;s resolution to write some sort of an update every week. That went out the window pretty quickly. Especially now that I&amp;rsquo;ve taken over the Inner Product column for Game Developer Magazine and that&amp;rsquo;s taking away some of my writing time (check out the May issue for my first column!).&lt;br&gt;
It turns out that Charles&amp;rsquo; old article &lt;a href="http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/" title="Stupid C++ Tricks: Adventures in Assert"&gt;Stupid C++ Tricks: Adventures in Assert&lt;/a&gt; is one of our most viewed entries, even after all this time. So I figured I&amp;rsquo;d follow it up with a really, really simple C++ trick. It&amp;rsquo;s almost trivial, really, but I&amp;rsquo;ve totally fallen in love with it. At first, when Charles introduced me to it, I was kind of lukewarm. But now I&amp;rsquo;m finding myself going through refactoring rampages in the code changing things to be this way. Intrigued? Read on.&lt;/p&gt;</description><content:encoded><![CDATA[<p>So much for the new year&rsquo;s resolution to write some sort of an update every week. That went out the window pretty quickly. Especially now that I&rsquo;ve taken over the Inner Product column for Game Developer Magazine and that&rsquo;s taking away some of my writing time (check out the May issue for my first column!).<br>
It turns out that Charles&rsquo; old article <a href="http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/" title="Stupid C++ Tricks: Adventures in Assert">Stupid C++ Tricks: Adventures in Assert</a> is one of our most viewed entries, even after all this time. So I figured I&rsquo;d follow it up with a really, really simple C++ trick. It&rsquo;s almost trivial, really, but I&rsquo;ve totally fallen in love with it. At first, when Charles introduced me to it, I was kind of lukewarm. But now I&rsquo;m finding myself going through refactoring rampages in the code changing things to be this way. Intrigued? Read on.</p>
<p>C++ enums are great in practice, but they&rsquo;re a bit lacking once you really start flexing them. Don&rsquo;t get me wrong, they&rsquo;re definitely a step up from #defines, but you can&rsquo;t help but wish for more. Type safety is only so-so (enums get promoted to ints silently), you can&rsquo;t forward declare them so you&rsquo;re forced to have extra includes, you can&rsquo;t split up a declaration of enums across multiple files (the compiler would have to do more work, but it would be awesome to be able to create uids for different classes in their own header files instead of a global one). But the most grating of design decisions is their scoping rules.<br>
Take for example a set of enums describing the game flow:</p>
<pre tabindex="0"><code>enum GameFlowType
{
    Run,
Â    Exit,
   Â Restart,
   Â Restore,
};
</code></pre><p>Now functions can return a GameFlowType to indicate that the main loop should do. So far so good.</p>
<p>Except that, look at how it&rsquo;s used:</p>
<pre tabindex="0"><code>GameFlowType DoMainLoop(bool render)
{
    //...
   Â if (someCondition)
       Â return Exit;
   Â return Run;
}
</code></pre><p>Ouch! We&rsquo;ve managed to pollute the global namespace with totally generic keywords such as Run and Exit. What if I want to have an enum that controls what action an AI is going to take:</p>
<pre tabindex="0"><code>enum AIAction
{
Â Â Â  Enter,
Â Â Â  Exit,
Â Â Â  Stop,
Â Â Â  Walk,
Â Â Â  Run,
};
</code></pre><p>That won&rsquo;t even compile because the symbols conflict with the GameFlowType ones. Even worse, it will compile just fine if they don&rsquo;t happen to be included in the same compilation unit. So you might be fine all along until you write some AI code that has control over the game flow. Oops!<br>
OK, so you can prefix all your enums like this:</p>
<pre tabindex="0"><code>enum GameFlowType
{
    GameFlowTypeRun,
    GameFlowTypeExit,
    GameFlowTypeRestart,
    GameFlowTypeRestore,
};
</code></pre><p>and</p>
<pre tabindex="0"><code>enum AIAction{
    AIActionEnter,
    AIActionExit,
    AIActionStop,
    AIActionWalk,
    AIActionRun,
};
</code></pre><p>That will technically fix the problem, but it&rsquo;s a bit ugly, and we&rsquo;re still polluting the global namespace (what if I wanted to have a class called AIActionEnter?).</p>
<p>Another potential solution is to score the enum inside the class that is using them. So we could have:</p>
<pre tabindex="0"><code>class AIAction{
public:
    enum AIActionType
    {
        Enter,
        Exit,
        Stop,
        Walk,
        Run,
    };
};
</code></pre><p>Much cleaner, do doubt, but also with its share of problems: First of all, it forces you to associate a set of enums with a class, which is not something you always want to do. But the biggest problem is that as soon as you have more than one set of enums per class, they all get promoted to the same scope:</p>
<pre tabindex="0"><code>class AIAction
{
public:
    enum AIActionBehavior
    {
        Enter,
        Exit,
        Stop,
        Walk,
        Run,
    };

    enum AIActionGroup
    {
        None,
        Self,
        Team,
        All,
    };
};
</code></pre><p>When we see one of those enums in code referred to as AIAction::Self, we really have no idea that it&rsquo;s referring to that group the action is applied to, as opposed to AIAction::Enter, which is the type of action.<br>
Our solution? Move all enums into a descriptive namespace.</p>
<pre tabindex="0"><code>namespace GameFlowType
{
    enum Enum
    {
        Invalid,
        Run,
        Exit,
        Restart,
        Restore,
    };
}
</code></pre><p>When you have a variable of that enum type, it&rsquo;s listed as GameFlowType::Enum type, which clearly indicates what it does. And its values are referred to as GameFLowType::Exit. You get the ideal scoping, you&rsquo;re not tied to any particular class, things are explicit but not verbose, you&rsquo;re no polluting the global namespace, and it&rsquo;s doesn&rsquo;t affect the runtime or compilation times.<br>
Sometimes the best solutions are the simplest ones.</p>]]></content:encoded></item><item><title>UnitTest++ v1.0 Released</title><link>https://gamesfromwithin.com/unittest-v10-released/</link><pubDate>Sun, 19 Mar 2006 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/unittest-v10-released/</guid><description>&lt;p&gt;We grabbed the best features of each framework and created what we think it&amp;rsquo;s the best C++ unit-testing framework out there (for our needs anyway). We took the results and put them up in Sourceforge under a veryunrestrictive license, and that&amp;rsquo;s how UnitTest++ was born.&lt;/p&gt;</description><content:encoded><![CDATA[<p>We grabbed the best features of each framework and created what we think it&rsquo;s the best C++ unit-testing framework out there (for our needs anyway). We took the results and put them up in Sourceforge under a veryunrestrictive license, and that&rsquo;s how UnitTest++ was born.</p>
<p>I had been using a modified version of CppUnitLite for quite a while, slowly fixing the parts in need of mending, and adding new functionality as it became needed. Eventually I released most of those changes as CppUnitLite2, and I thought that would be the end of that. It turns out that was just the beginning.</p>
<p>Shortly after that, several people started emailing me with new functionality, fixes, patches, suggestions, etc. At the same time, <a href="http://cnicholson.net/">Charles Nicholson</a> was starting to get quite a bit of response as well for his own testing framework, sometimes with similar fixes and suggestions.</p>
<p>If this was going to grow to be a real project, developing over time, supporting users&rsquo; needs, and accepting code contributions, clearly it would make sense to join forces. And that&rsquo;s exactly what we did. We grabbed the best features of each framework and created what we think it&rsquo;s the best C++ unit-testing framework out there (for our needs anyway).</p>
<p>We took the results and put them up in <a href="http://sourceforge.net/projects/unittest-cpp/">Sourceforge</a> under a <a href="http://en.wikipedia.org/wiki/MIT_License">very unrestrictive license</a>, and that&rsquo;s how <a href="http://unittest-cpp.sourceforge.net/">UnitTest++</a> was born.</p>
<p>Our ultimate goal is to apply test-driven development to game development. All of the existing frameworks fell short in one area or another. Specifically, the driving forces behind the design of UnitTest++ are:</p>
<ul>
<li>Portability. As game developers, we need to write tests for a variety of platforms, most of which are not supported by normal software packages (all the game consoles). So the ability to easily port the framework to a new platform was very important.</li>
<li>Simplicity. The simpler the framework, the easier it is to add new features or adapt it to meet new needs, especially in very limited platforms.</li>
<li>Development speed. Writing and running tests should be as fast and straightforward as possible. We&rsquo;re going to be running many tests hundreds of times per day, so running the tests should be fast and the results well integrated with the workflow.</li>
</ul>
<p>UnitTest++ is a fully featured testing framework, with many of the features you may expect from Xunit-style frameworks such as fixtures and reporting. Additionally, here are some of the specific features that make UnitTest++ unique:</p>
<ul>
<li>Minimal work required to create a new test. For TDD development, we write lots and lots of tests, so creating a new test should be as quick and painless as possible. UnitTest++ does not require explicit test registrations, and creating new tests requires minimal work.</li>
<li>Good assert and crash handling. When automated tests are executed, it&rsquo;s very important not to hang the process or abort the tests any time the program crashes or an assert fails. UnitTest++ will catch and report exceptions as failed tests and print a lot of information about them. It will translate signals to exceptions as well as be able to catch invalid memory accesses and other problems.</li>
<li>Minimal footprint and minimal reliance on heavy libraries. When you intend to run tests on a <a href="http://www.research.ibm.com/cell/SPU.html">Cell SPU</a> with a measly 256 KB of RAM, you really want to be as lean and mean as possible. UnitTest++ is very lightweight, and it will get even lighter weight once strstream is replaced.</li>
<li>No dynamic memory allocations done by the framework, which makes it much easier to track memory leaks and generally more attractive for embedded systems.</li>
<li>Multiplatform support. Right now it supports Win32, Linux, and Mac OS X out of the â€œbox,â€ and other platforms will probably work without any changes. The source code makes use of platform-specific functions whenever necessary, so it is easy to hook up special timers, allocators, or reporters for specific platforms. The code comes with a makefile as well as with project and solution files for Visual Studio 2003 and 2005.</li>
<li>Full set of unit tests for itself. UnitTest++ was TDD&rsquo;d from the ground up, including some of the ugly macros (imagine how much fun it was bending the framework to test itself that way!). It goes without saying, all the tests are included with the source code, so you can go totally wild with them :-)</li>
</ul>
<p>This was just the first release. UnitTest++ is ready for full production work, but we already have plans beyond this release. This is a peek at some of the features we have in mind for upcoming versions:</p>
<ul>
<li>Out-of-the-box support for game console platforms (Xbox 360, PS3 PPU and SPU, and Nintendo Revolution). Of course, this is dependent on us getting permission from the console manufacturers to release some code that works with their SDK.</li>
<li>Ability to trade some features (such as rich check reporting) for some extra memory. In some platforms, like Cell SPUs, you really need to go barebones.</li>
<li>Suites to group tests together.</li>
<li>Different reporters (HTML, GUIs, etc). Don&rsquo;t worry, all those modules will be optional and well separated, so they won&rsquo;t affect the simplicity of the framework.</li>
<li>Per-test timings. Maybe the ability to flag some tests as not exceeding a certain amount of time, or just failing any test that goes over a threshold.</li>
<li>Built-in memory leak detection.</li>
</ul>
<p>So that&rsquo;s it. <a href="http://sourceforge.net/project/showfiles.php?group_id=158151">Download the source code</a> and give it a try. We welcome any comments and suggestions (best channels would be through the <a href="https://lists.sourceforge.net/lists/listinfo/unittest-cpp-devel">project mailing list</a> or comments here). We hope you find it useful and that it makes your TDDing even more productive.</p>]]></content:encoded></item><item><title>CppUnitLite2 1.1</title><link>https://gamesfromwithin.com/cppunitlite2-11/</link><pubDate>Sun, 18 Dec 2005 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/cppunitlite2-11/</guid><description>&lt;p&gt;At this point, we have been using CppUnitLite2 for a year at High Moon Studios doing test-driven development on Windows, Xbox 360, and some PS3. It has been used to unit test libraries of an engine, pipeline tools, GUI applications, and production game code.&lt;/p&gt;</description><content:encoded><![CDATA[<p>At this point, we have been using CppUnitLite2 for a year at High Moon Studios doing test-driven development on Windows, Xbox 360, and some PS3. It has been used to unit test libraries of an engine, pipeline tools, GUI applications, and production game code.</p>
<p><a href="/wp-content/uploads/bin/CppUnitLite2_1_1.tar.gz"><img alt="icon" loading="lazy" src="/cppunitlite2-11/images/script.png">CppUnitLite2_1_1.tar.gz</a></p>
<p>About a year ago, I wrote <a href="/exploring-the-c-unit-testing-framework-jungle/">an article comparing unit test frameworks</a> that went to become one of the most popular in this site. The article concluded with the recommendation of one of the less well known frameworks: CxxTest.</p>
<p>Shortly after writing that article, it came time to roll out test-driven development at work. Interestingly, once I weighted in all the requirements, I ended up not following my own advice. Instead, I decided to go with a customized version of CppUnitLite, which was listed in the article as the second choice. The idea of an extremely simple unit testing framework was too attractive to pass up in an environment where we have to support a large variety of environments and target platforms.</p>
<p>At this point, we have been using CppUnitLite2 for a year at <a href="http://www.highmoonstudios.com/">High Moon Studios</a> to do TDD on Windows, Xbox 360, and some PS3 (we even have a stripped-down version that runs on a <a href="http://cell.scei.co.jp/e_download.html">PS3 SPU</a>). It has been used to unit test libraries of an engine, pipeline tools, GUI applications, and production game code.</p>
<p>CppUnitLite2 was originally released along with my article a year ago. It was a heavily modified version of the original CppUnitLite by Michael Feathers. This version introduces the changes we made at work as different issues came up and we needed more functionality from the framework. In particular, <a href="http://www.tilander.org/jim/">Jim Tilander</a> and <a href="http://cnicholson.net/content.php?id=1">Charles Nicholson</a> were responsible for a lot of those changes. By now, I doubt there&rsquo;s a single line left from the original code. Additionally, CppUnitLite2 itself has a set of tests using itself in an interestingly recursive way.</p>
<h3 id="whats-new">What&rsquo;s new</h3>
<p><strong>Fixtures created and destroyed around each test.</strong></p>
<p>I can&rsquo;t believe that the original version of CppUnitLite2 didn&rsquo;t have this feature. It was the biggest glaring problem with the framework (I even pointed it out in the article). Each fixture used to be created at static initialization time, which, apart from being a really bad idea, caused a lot of objects to be created and live in memory at the same time. Considering that some of those objects would initialize/shutdown some important game systems, we clearly needed to manage their lifetime a bit better.</p>
<p>The test macro was changed to register a temporary test with the TestRegistry, which in turn will create the fixture at execution time. Now fixtures and tests are created just before each test, and destroyed right after, just as you would expect from any sane framework.</p>
<p>For those masochists out there, here&rsquo;s the ugly macro for a test with fixture in all its glory. Notice how the TestRegistrar registers the dummy test class that we created as part of the macro.</p>
<pre tabindex="0"><code> #define TEST_F(fixture, test_name)                                                      \ struct fixture##test_name : public fixture {                                        \ fixture##test_name(const char * name_) : m_name(name_) {}                       \ void test_name(TestResult&amp; result_);                                            \ const char * m_name;                                                            \ };                                                                                  \ class fixture##test_name##Test : public Test                                        \ {                                                                                   \ public:                                                                         \ fixture##test_name##Test ()                                                 \ : Test (#test_name &#34;Test&#34;, __FILE__, __LINE__) {}                       \ protected:                                                                      \ virtual void RunTest (TestResult&amp; result_);                                 \ } fixture##test_name##Instance;                                                     \ TestRegistrar fixture##test_name##_registrar (&amp;fixture##test_name##Instance);       \ void fixture##test_name##Test::RunTest (TestResult&amp; result_) {                      \ fixture##test_name mt(m_name);                                                  \ mt.test_name(result_);                                                          \ }                                                                                   \ void fixture ## test_name::test_name(TestResult&amp; result_)
</code></pre><p><strong>Improved check statements</strong></p>
<p>Another one of the major weaknesses of CppUnitLite as it stood was the check statements. You needed to have a custom check macro for each data type you cared to check. The generic CHECK_EQUAL macro will now work on any data type as long as it can be compared with operator == and output to a stream.</p>
<p>This version of CppUnitLite2 also includes some special macros to check arrays with one and two dimensions. Again, this works on any data type that supports operator == and operator[]. It came it very handy for checking equality of vectors and matrices in a game engine. For example, the following code checks that two matrices are equal:</p>
<p>CHECK_ARRAY2D_CLOSE (m1, m2, 4, 3, kEpsilon);</p>
<p>Ironically, in some heavily restricted environments (like the PS3 cell processors), we can&rsquo;t use streams, so in that case we&rsquo;re forced to go back to the old specialized check macros.</p>
<p><strong>Invariant statements in checks</strong></p>
<p>Another really annoying feature of the previous version of CppUnitLite2 was that the code in a check statement was called multiple times, which could cause strange side effects.</p>
<p>Consider the following code:</p>
<p>CHECK_EQUAL (FunctionWithSideEffects1(), FunctionWithSideEffects1());</p>
<p>The way the check statement was expanded out, both those functions could be evaluated multiple times. If the functions had side effects, they would be executed several times, causing unexpected results (for example, the check could fail but the printed result could be different). The fix wasn&rsquo;t trivial because we couldn&rsquo;t save off the value of each statement because they could be of any type and we have no way of finding the type from within the macro.</p>
<p>The check macro now expands out to a templated function, which is able to evaluate both statements only once and work with the saved value to avoid any surprising side effects.</p>
<p><strong>Optional fixture initialization</strong></p>
<p>As we continued hammering on the unit test framework for all our development, one clear pattern appeared that wasn&rsquo;t handled by the framework: Being able to create fixtures with parameters defined in the test. For example, the fixture might do ten different steps, but we want to set a particular value in one of those steps, and by the time control reaches the test code itself it&rsquo;s too late.</p>
<p>We started getting around that by creating different fixtures, and then by inhereting from other fixtures and changing some parameters. Both of those solutions were less than ideal (lots of code duplication and added complexity). Things got out of hand when we made the fixtures a templated class on a value, and created them by specifying the value as part of the texture name. Now it was a pain to debug and things were even less clear.</p>
<p>So we finally implemented it natively in CppUnitLite2 as fixtures with initialization parameters. We introduced a new macro, TEST_FP (test with fixture and parameters), which takes any parameters you want to pass to the fixture constuctor.</p>
<p>Now you can declare tests like this:</p>
<p>TEST_FP (VectorFixture, VectorFixture(10), MyTest) { }</p>
<p>We should prob ably simplify that to avoid repeating the fixture name, but that works fine for now.</p>
<p><strong>Include cleanup</strong></p>
<p>The original version of CppUnitLite was pretty casual about what headers it included. Unfortunately, that means that all test code were automatically exposed to a variety of standard headers, whether you wanted it or not. This version is a lot more strict, and the only header that will get pulled in from using it will be iosfwd, which is even a fairly lightweight one.</p>
<p><strong>Memory allocations</strong></p>
<p>We have very strict memory allocation wrappers around our tests, and if any memory leaks, it is reported as a failed test. Since checking for memory allocations is very platform specific, it is left out of the framework (although it could be added pretty easily in the platform-specific sections). In any case, some of the static-initialization time allocations were confusing the memory tracker, so we removed them completely. All it means is that we use an array to register tests instead of a std::vector and we cap the maximum number of tests to a fixed amount. If you need more than the default 5000 tests, go right ahead and add a few zeros.</p>
<p><strong>New license</strong></p>
<p>Previous versions of CppUnitLite were not released with an explicit license. To make things clear, I explicitly added the license text for the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a> with an added restriction. The MIT license allows you to use the code in any project, commercial or otherwise, without any restrictions. The added restriction to the license prohibits its use in any military applications or projects with any military funding.</p>
<h3 id="ratings">Ratings</h3>
<p>How does this release of the CppUnitLite2 compare with respect to my initial set of features I used to rate the different unit tests frameworks?</p>
<ul>
<li><strong>Minimal amount of work needed to add new tests.</strong> Nothing has changed there. Still passes with flying colors.</li>
<li><strong>Easy to modify and port.</strong> That has always been the strong suite of this framework.</li>
<li><strong>Supports setup/teardown steps (fixtures).</strong> Much improved now by creating them correctly around each test.</li>
<li><strong>Handles exceptions and crashes well.</strong> No changes there. Still one of the best I&rsquo;ve seen.</li>
<li><strong>Good assert functionality.</strong> The check macros have been much improved to match the best frameworks out there.</li>
<li><strong>Supports different outputs.</strong> Yup. Still there.</li>
<li><strong>Supports suites.</strong> It still doesn&rsquo;t. It just shows that I really haven&rsquo;t needed this feature yet.</li>
</ul>
<h3 id="future-work">Future work</h3>
<p>So, what&rsquo;s next for CppUnitLite2? It&rsquo;s really quite usable right now, but I could see a few changes happening in the next year, and maybe a few others will come up and surprise me.</p>
<p>Test registration is based on static initialization of global variables, which is not very reliable across compliers. For example, if you try to put the tests in a static library, MSVC will strip out the registration code leaving you with no tests. To get around that, we could introduce a custom build step in a scripting language that would generate a simple file with explicit registration of tests. This could also be used to collect tests from many different libraries into a single executable.</p>
<p>A couple of times it would have been convenient to have parameterized tests (I think that&rsquo;s the correct term for it). Basically, to have tests that could run with different data. Something like this:</p>
<pre tabindex="0"><code> TEST_PARAM(MyCustomTest, int a, int b) { CHECK (something); CHECK(something else); CHECK(yadda yadda); }  TEST(MyTest) { CALL_TEST(MyCustomTest, 10, 5); } TEST(MyTest) { CALL_TEST(MyCustomTest, 12, 7); }
</code></pre><p>The key point is that a test fails in the parameterized test, it should report the error correctly indicating where it came from.</p>
<p>This is actually pretty easy to implement with a couple of macros. We simply haven&rsquo;t needed it more than a couple of times, so we haven&rsquo;t bothered yet. But I imagine next time we run up against this we&rsquo;ll bite the bullet and implement it.</p>
<h3 id="wrap-up">Wrap-up</h3>
<p>Charles had so much fun working with this framework, he decided to write his own from scratch. He made <a href="http://cnicholson.net/content.php?id=52">it available on his web site</a>, so go check it out.</p>
<p>Thanks to High Moon Studios for being open and letting us release the changes we made and share them back with everybody. If you end up using the framework and you make any changes, drop me an email and I&rsquo;ll add them for the next release.</p>]]></content:encoded></item><item><title>Are We There Yet? SlickEdit's C++ Refactoring</title><link>https://gamesfromwithin.com/are-we-there-yet-slickedits-c-refactoring/</link><pubDate>Tue, 11 Oct 2005 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/are-we-there-yet-slickedits-c-refactoring/</guid><description>&lt;p&gt;Jumbo shrimp. Instant classic. Military intelligence. C++ refactoring browser. Spot the pattern yet? Up until recently, there have been more sightings of &lt;a href="http://www.lochness.co.uk/livecam/"&gt;Nessy&lt;/a&gt; and &lt;a href="http://www.unmuseum.org/bigfoot.htm"&gt;Bigfoot&lt;/a&gt; than of working C++ refactoring browsers. After months of using refactoring intensively in C++, my fingers are screaming for mercy and threatening me with repetitive stress syndrome. Fortunately, things seem to be changing a bit. I recently learned of &lt;a href="http://www.slickedit.com/"&gt;SlickEdit&lt;/a&gt;&amp;rsquo;s support for C++ refactoring, so I couldn&amp;rsquo;t resist taking it for a test drive.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Jumbo shrimp. Instant classic. Military intelligence. C++ refactoring browser. Spot the pattern yet? Up until recently, there have been more sightings of <a href="http://www.lochness.co.uk/livecam/">Nessy</a> and <a href="http://www.unmuseum.org/bigfoot.htm">Bigfoot</a> than of working C++ refactoring browsers. After months of using refactoring intensively in C++, my fingers are screaming for mercy and threatening me with repetitive stress syndrome. Fortunately, things seem to be changing a bit. I recently learned of <a href="http://www.slickedit.com/">SlickEdit</a>&rsquo;s support for C++ refactoring, so I couldn&rsquo;t resist taking it for a test drive.</p>
<p><a href="http://www.nobugs.org/developer/parsingcpp/">C++ refactoring is hard</a>. There&rsquo;s no doubt about that. Just parsing C++ is hard, as I quickly found out when <a href="/physical-structure-and-c-part-2-build-times/%20">I wrote some scripts a couple of years ago</a> to analyze the structure of a C++ program. Even with the help of Doxygen pre-processing, my analysis was full of holes and exceptions. Writing a robust program to correctly interpret and modify the structure of a C++ program is a nightmare come true.</p>
<p>Frankly, I had pretty much given up all hope of every having good automated refactoring tools for C++. My best hope was that new language designers keep refactoring in mind as a primary goal of their languages, so at least we&rsquo;ll have those tools in whatever language we&rsquo;re programming with in ten years.</p>
<p>So along comes SlickEdit version 10 with great promises of C++ refactoring. Surprisingly enough, that&rsquo;s just one small bullet point completely hidden by a bunch of bullet-point items of no great interest or uniqueness (smart line selections? keyboard emulation? what year is this, 1992?). As a matter of fact, refactoring isn&rsquo;t even mentioned in SlickEdit&rsquo;s &ldquo;<a href="http://www.slickedit.com/content/view/353/217/">cool features</a>&rdquo; web page! That&rsquo;s not an auspicious beginning.</p>
<p>Fortunately, things get better. The installation for the Linux demo version of SlickEdit v10 worked without a hitch. The refactoring actions feature prominently in the Tools menu and the right-click context menu. I loaded a small project I was working on (just a handful of classes-nothing big) and started applying them one at the time.</p>
<h4 id="rename">Rename</h4>
<p><img alt="nessy" loading="lazy" src="/are-we-there-yet-slickedits-c-refactoring/images/nessy.jpg"> This is the big one. If I can only have one refactoring, I&rsquo;ll take this one. Being able to rename variables, functions, and classes takes care of 75% of the refactorings I do. A tool that could reliably do that would be a major productivity boost (reliably being the key word there).</p>
<p>How does SlickEdit&rsquo;s rename work? Member variables were a dream to rename. But frankly, I can usually do that with &ldquo;replace in file&rdquo; and doing one edit in the header file, so that&rsquo;s not very challenging. Still, good start.</p>
<p>Trying to rename member functions was not quite as successful. Sometimes it would work like a charm, and rename the function in the cpp file, the header file, and everywhere else it was called from. Sometimes however, it would look at my code and proclaim that there was nothing to rename. Nothing? I had just right clicked on top of the function to rename! Some other times it would rename the function in a couple of classes and totally miss where it was being used.</p>
<p>After some experimentation, it turns out that &ldquo;Quick Rename&rdquo; (which supposedly is not nearly as robust) worked time and time again without a single problem. That&rsquo;s good I guess, but it left me with a very uneasy feeling.</p>
<p>Thumbs up for the user interface for refactoring too. As soon as you enter your refactoring and your parameters, you are presented with a list of the files that will be modified and a diff of each of them, so you can cancel the operation if something went horribly wrong. It certainly makes you feel a lot more in control.</p>
<h4 id="extract-method">Extract method</h4>
<p>This is a fairly common refactoring. I actually thought it would be fairly complicated, but in every test I did, SlickEdit handled it admirably. The tricky part is to figure out what arguments the new function needs to take, and every time it figured it out correctly. You even get an option to name the new function and tweak the arguments it takes before applying the refactoring. Again, great user interface.</p>
<p>My only quibble with this refactoring is that the new methods are all made public. Uh? Would it have been so difficult to give us an option? If anything, I have just moved code from a member function to another member function in that class. By default it should be private, not public. Oh well, I just have to move one line. But it&rsquo;s a bit annoying to have to tweak the header file by hand.</p>
<h4 id="modify-parameter-list">Modify parameter list</h4>
<p>Another big one. Sometimes it&rsquo;s quite painful to add a new parameter to a function that is called from dozens or hundreds of tests. So much so that it really discourages us from doing the &ldquo;right&rdquo; thing and is tempting to create a new function instead. Sometimes, after the second time you need to add a new parameter, we just create a struct with the parameters that the function takes and save some pain in the future. Not a particularly elegant solution, so this refactoring tool would come in very handy.</p>
<p>Unfortunately this one completely failed for me. Most of the time, trying to add a new parameter to a function would just come back and tell me there&rsquo;s nothing to do. Same thing with rearranging the order of parameters. At best, once I got it to actually add the new parameter, it only changed the function and the header file, not the calling code. Doh!</p>
<h4 id="misc-inheritance-chain-refactorings">Misc inheritance chain refactorings</h4>
<p>SlickEdit has a set of refactorings intended to do operations in the inheritance chain: push down, pull up, extract super class, etc. I don&rsquo;t work with big inheritance chains these days, so they&rsquo;re not very useful to me and I didn&rsquo;t test them at all. Actually, now that I think about it, the only inheritance I use are interfaces and mock objects. Then again, I suspect this would be extremely handy for manipulating legacy code (like some currently popular game engines).</p>
<h4 id="extract-class">Extract class</h4>
<p>This seems like a really large refactoring. Extracting a whole class out of a set of code? Rename didn&rsquo;t work consistently, and modify parameter list didn&rsquo;t work at all. I certainly wouldn&rsquo;t want to try something of this magnitude. Let&rsquo;s get the other ones working before we jump on this one.</p>
<h4 id="convert-local-to-field">Convert local to field</h4>
<p>This one seems marginally useful, and it&rsquo;s not something I do in a regular basis. All it does is to prepend an m_ to the variable and add it to the header file. What if you don&rsquo;t prefix your member variables with m_? Is there a way to turn that off? Also, the new member variable wasn&rsquo;t added to the constructor(s) initialization list.</p>
<h4 id="move-method">Move method</h4>
<p>At first I thought that it was a totally pointless refactoring since it&rsquo;s describing as moving a method from one class to another (I can&rsquo;t remember when was the last time I did that). But it turns out it can be quite useful to move a non-member function into a class. That&rsquo;s something I do sometimes when a helper function in an anonymous namespace starts needing more and more state from the object that uses it, and eventually it becomes clear that it wants to be a member function.</p>
<p>Move method will make it a static member function, and then you can follow that up with Convert static method to instance method and voila.</p>
<h4 id="encapsulate-field">Encapsulate field</h4>
<p>I&rsquo;m sure some people will rave about this one, but I&rsquo;m not too thrilled about it. It creates set/get methods of a member variable. Frankly, I don&rsquo;t like set/get methods. I think that, most of the time, they&rsquo;re a smell of bad design. I&rsquo;m not sure I want to make it any easier for people to create them, so I would be happier without this refactoring tool at all. Besides, what&rsquo;s with making them inline by default? At least give us an option to put them in the cpp file.</p>
<h4 id="replace-literal-with-declared-constant">Replace literal with declared constant</h4>
<p>This one takes a literal (magic number/string) and replaces with with a constant or a define. Now we&rsquo;re really reaching the bottom of the barrel. Is it really faster to navigate a three-level menu to select this than to do it by hand? It&rsquo;s good that you get an option to create the new constant as const, static const, or an evil #define, but it doesn&rsquo;t place it in an anonymous namespace, even if one already exists in that compilation unit.</p>
<h4 id="create-standard-methods">Create standard methods</h4>
<p>This one will add a constructor, destructor, copy constructor, and assignment operator to the class. At first I thought it wasn&rsquo;t a big deal. I already have macros that do that for new classes. Then I realized you can do this with an existing class, and it will take care of assigning all member variables. That&rsquo;s pretty cool, but of limited practical use. I haven&rsquo;t had to go back to many existing classes and add assignment operators. Still, I could see how it could be useful.</p>
<p><img alt="yeti" loading="lazy" src="/are-we-there-yet-slickedits-c-refactoring/images/bigfoot.jpg"> All in all, SlickEdit managed to impress me because I wasn&rsquo;t really expecting functional C++ refactorings. On the other hand, it is clearly far from being robust enough to be relied upon for production work. Maybe the next version? For me, they just need to fix the rename and I&rsquo;m almost there.</p>
<p>One cool aspect of SlickEdit is its powerful scripting language, where it has access to all the commands you can do from the menu. That means that I can write a script that, as part of what it does, kicks off some refactoring step. That&rsquo;s extremely useful to adapt the refactorings to my own environment. One thing I didn&rsquo;t see is whether the script language has access to the logical structure of the C++ program or whether it&rsquo;s just limited to calling the refactoring function. It would be great to have more control and be able to create custom refactorings.</p>
<p>SlickEdit is a bit puzzling because it parses all the header files during each refactoring. And by all, I mean all. Not just the ones in your projects, but all the standard include files that you might have included. I don&rsquo;t really understand why it does that. I&rsquo;m clearly not going to change standard header files, so I think that limiting a refactoring only to files that are presently loaded in the project would be good. With my toy projects with a handful of classes, the refactorings were very fast (a second or two), but I fear how it might scale to a large project. Next time they have an improved version I&rsquo;ll have to load it up with a large codebase and see how it fares.</p>
<p>It seems as if refactoring tools for C++ are just around the corner, but still tantalizingly out of reach. At this point I&rsquo;m not ready to switch to SlickEdit based on the strength of its refactoring tools alone, although I&rsquo;m still going to take a closer look at it. Right now I would prefer a standalone command-line refactoring tool that could be easily integrated in any environment. Anybody knows of any other decent C++ refactoring tools?</p>]]></content:encoded></item><item><title>Asserting Oneself</title><link>https://gamesfromwithin.com/asserting-oneself/</link><pubDate>Mon, 03 Oct 2005 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/asserting-oneself/</guid><description>&lt;p&gt;I&amp;rsquo;ve been following the discussion on &lt;a href="http://www.lenholgate.com/archives/000500.html"&gt;the evils of assert&lt;/a&gt; started by &lt;a href="http://www.lenholgate.com/"&gt;Len Holgate&lt;/a&gt;. Poor old assert was &lt;a href="http://lapthorn.net/index.php?id=87"&gt;getting beaten up&lt;/a&gt; from &lt;a href="http://sleeksoft.co.uk/public/techblog/articles/20050926_1.html"&gt;every side&lt;/a&gt;, so I&amp;rsquo;m going to have to step forward and defend it.&lt;/p&gt;
&lt;p&gt;Yes, I do find assert useful. Yes, I&amp;rsquo;m doing full-out test-driven development. Yes, I&amp;rsquo;m a hardcore C++ programmer.&lt;/p&gt;</description><content:encoded><![CDATA[<p>I&rsquo;ve been following the discussion on <a href="http://www.lenholgate.com/archives/000500.html">the evils of assert</a> started by <a href="http://www.lenholgate.com/">Len Holgate</a>. Poor old assert was <a href="http://lapthorn.net/index.php?id=87">getting beaten up</a> from <a href="http://sleeksoft.co.uk/public/techblog/articles/20050926_1.html">every side</a>, so I&rsquo;m going to have to step forward and defend it.</p>
<p>Yes, I do find assert useful. Yes, I&rsquo;m doing full-out test-driven development. Yes, I&rsquo;m a hardcore C++ programmer.</p>
<p>Before we even get started, let me recap what I see as the main reasons to use assert.</p>
<ul>
<li>Detect a program error or bug right away. The sooner the better. There&rsquo;s nothing more frustrating than trying to track down bugs that occurred several function calls away, especially if they&rsquo;ve unwound the stack and started a new series of calls. Even worse are errors that propagate and don&rsquo;t become apparent until several frames later.Example: Creating a new character from a spwan point during gameplay should always work, so asserting on the pointer returned by the factory is a good idea.</li>
<li>Document a decision, limitation, or assumption of particular functions. Nothing like calling a function and getting an assert right away to realize that&rsquo;s not the way it was intended to be used.Example: A function that takes a pointer that can never be NULL and we don&rsquo;t want to take a reference (maybe because the object is going to store and keep ownership of the pointer).</li>
<li>Catch bad situations that will soon lead to trouble.Example: Asserting that the matrix passed to a rotate function is orthonormal. Everything will work fine for a little while if it isn&rsquo;t, but soon things will degenerate if errors keep accumulating.</li>
</ul>
<p><img alt="stop" loading="lazy" src="/asserting-oneself/images/stop.jpg"> One key point about the use of assert is that it&rsquo;s a message from the programmers to the programmers and nobody else. The idea is that whatever caused that assert is a top priority and should be fixed right away. An end user should never see an assert message because a) they don&rsquo;t care and b) it means their program is toast.</p>
<p>This distinction between programming errors and &ldquo;user&rdquo; errors is particularly important in game development. User errors are anything that a user of the tools or game could cause just by using it. In our case that includes the content creators (designers and artists). The last thing we want to do is stop everything just because they typed the wrong file, or tried to load an old version of a model. Those errors need to be caught and dealt with. They are expected.</p>
<p>Programming errors are the ones that can only be caused by something done by a programmer in the code. As an example, in game development we constantly have functions that look like this: void Something::Update(float deltaTimeInSec). Unless you have a simulation system that can go both forwards and backwards, trying to call that function with negative seconds is nonsensical. An assert there tells the programmer that something either went horribly wrong, or they&rsquo;re trying to use Update in a way it wasn&rsquo;t intended. Clearly, no user of the program will ever be able to call Update with a negative time value just by using the program. So in this case, I do want to assert and have that fixed right away.</p>
<p>With that out of the way, let&rsquo;s look at Len&rsquo;s <a href="http://www.lenholgate.com/archives/000525.html">five major complaints about assert</a>. Let&rsquo;s take them one at the time.</p>
<h4 id="1-the-check-will-go-away-in-a-release-build">1. The check will go away in a release build.</h4>
<p>From my point of view, an assert is a way to tell a programmer (probably even myself in the future) that something has gone completely wrong. If an assert ever goes off, it&rsquo;s a bug in the code and a programmer needs to fix it.</p>
<p>So what if asserts go away in release builds? We&rsquo;re writing &ldquo;shrink-wrapped&rdquo; software, so that&rsquo;s a good thing because there will be no programmers around with their handy debugger to fix the problem. If a user ever manages to come up with a way to cause the code to get in a bad state, then all we can do is pray. Especially in the case of console games, trying to capture traces and exception reports is not going to help anybody.</p>
<h4 id="2-the-assert-is-covering-poor-design">2. The assert is covering poor design.</h4>
<p>I think this is really the crux of the discussion. Is assert really just a crutch for &ldquo;poor design&rdquo;? If you define good design as creating bullet-proof code that will work under <strong>any</strong> circumstance then it&rsquo;s probably right. But you know, my job is not to write bullet-proof code. My job is to write whatever needs to be written to satisfy our customer stories every two weeks, and eventually ship a game with it.</p>
<p>This is very much in the agile development mindset. I&rsquo;m not going to try to bomb-proof a piece of code for all foreseeable uses in the future. I&rsquo;ll make sure it does what it needs to do now and leave it at that. Under this view, asserts are post-it notes saying &ldquo;This code doesn&rsquo;t even handle this situation. You either screwed up, or you better update the code to deal with it.&rdquo;</p>
<p>Let&rsquo;s go back to the Update() function. What are our options to make it work without assert?</p>
<ul>
<li>Implement Update() to go backwards in time as well as forwards. That will easily more than double development effort for something that will have no effect in the final product (unless you&rsquo;re implementing a mechanic like <a href="http://www.amazon.com/exec/obidos/tg/detail/-/B00009ZVHY/ref=nosim/gamesfromwith-20">Sands of Time</a>, although I suspect that not even that game had a negative-time update).</li>
<li>Make it physically impossible to pass negative numbers into the Update function. We could create a delta time class that cannot be manipulated in any other way than to have positive values. While this is clearly possible, I feel it&rsquo;s a tradeoff between simplicity and &ldquo;bullet-proofness.&rdquo; I&rsquo;ll take simplicity any day of the week for most situations.</li>
<li>Have the update function check for negative values and return a failing value. That would be fine except that now everywhere we call Update we need to check for return values. Did you notice that Update(), the way it was declared, returned no values at all? That&rsquo;s a function that is supposed to work and never fail. What if an Update() function fails? What do we do next? Quietly move on to the next one, or try to fix the system in some way? I&rsquo;d rather slap the programmer with an assert and have him fix it right away than quietly continue to work while things are not working as expected.</li>
</ul>
<p>So I see it more as a tradeoff between simplicity, time, and robustness. There&rsquo;s no single correct answer, and it will depend on your particular situation. If you&rsquo;re writing flight-control software, to hell with simplicity and time constraints, and go for 100% robustness and throw a few redundant systems for good measure in case of cosmic rays interfering with the hardware. In my case, turnaround time and simplicity trump absolute robustness.</p>
<p>Also, I admit this might not work in every environment. It works for us because we&rsquo;re the only users of our own code. When something isn&rsquo;t good enough, we make it good enough. That&rsquo;s very different from writing a generic library for thousands of users to apply in their production code.</p>
<h4 id="3-the-assert-makes-it-very-hard-to-write-a-unit-test-for-the-failure-condition">3. The assert makes it very hard to write a unit test for the failure condition.</h4>
<p>I don&rsquo;t understand where this comes from. Maybe with a crappy unit-test framework it&rsquo;s a problem, but the unit-test framework I use deals with assertions just like any other exception, and fails the current test case. If your unit test framework barfs when your code tries to access an invalid pointer, you really need to look into getting a better one (I keep meaning to put up my version one of these days).</p>
<p>You should be able to hook up assert to anything you want (by using a custom assert or any other way you want). So the test runner first hooks up a special assert handler that throws a particular exception. Not only does this let us fail a test if an exception is triggered, but it even allows us to write tests to check that asserts are thrown. For example, I could write something like this:</p>
<pre tabindex="0"><code> TEST (UpdateWithNegativeTimeAsserts) { Whatever stuff; CHECK_ASSERT(stuff.Update(-0.1f)); }
</code></pre><h4 id="4-if-the-object-is-running-without-a-user-interface-then-the-asserts-dialog-box-may-cause-issues">4. If the object is running without a user interface, then the assert&rsquo;s dialog box may cause issues.</h4>
<p><img alt="oops" loading="lazy" src="/asserting-oneself/images/sign.jpg"> What dialog box? Maybe I&rsquo;ve been doing game development too long, but every single project I&rsquo;ve worked on has had a custom assert macro that gives us a lot more control than the standard one. Seriously, are people calling the standard assert() everywhere? No wonder they have issues.</p>
<p><a href="http://www.amazon.com/exec/obidos/tg/detail/-/1584500492/ref=nosim/gamesfromwith-20"><em>Game Programming Gems 1</em></a> had a great introduction to using custom asserts by <a href="http://www.aiwisdom.com/home_webmaster.html">Steve Rabin</a> with lots of great ideas (<a href="http://www.starforge.co.uk/free-linux.shtml">here&rsquo;s an implementation</a> based on his article). At the very least, you should be able to have full control of what you want the assert to do. A lot of the time that will simply be _asm int 3, but many other times you want to throw an exception, write out a log, send out an email, update a database, or even put up a dialog box to allow the user to bypass it. As a side note, I actually hate the option of continuing after an assert and I would never allow it in my own implementation. Assert means dead. Kaput. Done.</p>
<p>A custom assert takes five minutes to set up and will pay back in gold-pressed latinum in no time.</p>
<h4 id="5-the-assert-is-really-just-an-exploding-comment">5. The assert is really just an &ldquo;exploding comment.&rdquo;</h4>
<p>Yes, that&rsquo;s completely true. It&rsquo;s more like a programmer yelling in your ear &ldquo;YOU JUST SCREWED UP!&rdquo; But then again, that&rsquo;s one of the things that make unit tests so great. They&rsquo;re like comments that complain every time you change the behavior of the system in a way that violates what the tests are checking. Those are the best kind of &ldquo;comments.&rdquo;</p>
<p>That takes care of Len&rsquo;s objections. Clearly, I don&rsquo;t see any of them being an issue other than the second one, which is a matter of tradeoffs. Having said all that, I do use asserts less than I did before I used TDD. Unit tests take care of some of the things I would have checked with asserts in the past (did this loop really iterate over all the members that needed to be updated?), but unit tests still can&rsquo;t protect against misuse of functions or simply unexpected situations.</p>
<p>So no, I&rsquo;m not willing to give up on assert any time soon. It might be an ugly, rusty, oversized tool, but it still has a very definite spot in my toolbox.</p>]]></content:encoded></item><item><title>The Quest for the Perfect Build System (Part 2)</title><link>https://gamesfromwithin.com/the-quest-for-the-perfect-build-system-part-2/</link><pubDate>Tue, 20 Sep 2005 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/the-quest-for-the-perfect-build-system-part-2/</guid><description>&lt;p&gt;A couple of months ago I looked at &lt;a href="https://gamesfromwithin.com/the-quest-for-the-perfect-build-system/"&gt;various build systems&lt;/a&gt; in the hopes of finding an ideal one for C++ development. In particular, the most important criteria I was using was iteration time for incremental builds. Jam was the clear winner and things looked good.&lt;/p&gt;
&lt;p&gt;Fast-forward a few months and one aborted attempt at implementing that build system, and there are now more unanswered questions than answers. It turns out that Jam and its successors were far from the perfect solution I had envisioned, so I was back to square one. I took this opportunity to look into all the build systems I had left out of the first article, plus all the ones that other people asked me about since then, to come up with a much more comprehensive evaluation.&lt;/p&gt;</description><content:encoded><![CDATA[<p>A couple of months ago I looked at <a href="/the-quest-for-the-perfect-build-system/">various build systems</a> in the hopes of finding an ideal one for C++ development. In particular, the most important criteria I was using was iteration time for incremental builds. Jam was the clear winner and things looked good.</p>
<p>Fast-forward a few months and one aborted attempt at implementing that build system, and there are now more unanswered questions than answers. It turns out that Jam and its successors were far from the perfect solution I had envisioned, so I was back to square one. I took this opportunity to look into all the build systems I had left out of the first article, plus all the ones that other people asked me about since then, to come up with a much more comprehensive evaluation.</p>
<h3 id="the-contenders">The Contenders</h3>
<h4 id="jam">Jam</h4>
<p>Since <a href="http://www.perforce.com/jam/jam.html">Jam</a> is the culprit that caused this second go-around, I figured I would start with it. What&rsquo;s wrong with Jam? Isn&rsquo;t it the fastest kid on the block? It still is the fastest, but when it comes to supporting new platforms or adding new settings to builds, it&rsquo;s not the most straightforward of all systems.</p>
<p>Jam is a bit too complex for my tastes. Even after sitting for a while with the <a href="http://www.perforce.com/perforce/conf2001/wingerd/WPLaura.pdf">Jam tutorial</a> (which is a horrible introduction, by the way), reading the <a href="http://public.perforce.com/public/jam/src/Jam.html">skimpy documentation</a> many times, and playing around with some sample Jam files, it was still very difficult to create non-trivial Jam files. At that point, my best allies were the <a href="http://public.perforce.com/public/jam/src/Jambase.html">Jambase and Jamrules</a> files themselves. When it came time to start adding support for features such as precompiled headers, different build configurations, or Xbox 360 support, things got a lot harder very quickly.</p>
<p>Jam is a bit of a puzzle. Out of the &ldquo;box&rdquo; it claims to be able to have platform-independent Jam files, and that&rsquo;s the source of the problem, because it makes it a lot harder to support new platforms. In my case, since I&rsquo;m targeting a very specific set of platforms, I would much rather specify each build rule myself and have a simple, clean set, instead of a monster set of rules that applies to everything.</p>
<p>At the same time, Jam doesn&rsquo;t support some really basic features, such as spaces in filenames. Not like I advocate having spaces in filenames, mind you, but that&rsquo;s an unfortunate reality of the setup of many Windows computers. Yes, I know I can patch it, but this is where the next, and biggest, problem of Jam comes in.</p>
<p>Jam is dead.</p>
<p>Yes, Jam is completely dead. The <a href="http://maillist.perforce.com/mailman/listinfo/jamming">Jamming mailing list</a> has less traffic than a side road in Siberia during the winter. My attempts at asking there for help went completely unanswered (except for one kind soul who emailed me privately, apparently too embarrassed to post to a dead mailing list).</p>
<p>The fact that the latest official version of Jam dates back to 2002 should have been a good tipoff, but somehow I didn&rsquo;t catch on to that at first. The nail in the coffin was when I asked where the latest set of patches, or the latest unofficial version of Jam, was located and nobody, *nobody*, answered.</p>
<p>So where is everybody who developed and used Jam? Oh, they must have gone to one of Jam&rsquo;s successors, like BoostBuild. That&rsquo;s good, right? Right?&hellip;</p>
<h4 id="boostbuild-v2">BoostBuild v2</h4>
<p><a href="http://www.boost.org/tools/build/v2/">BoostBuild v2</a> is promising on paper. It builds on top of Jam to add several much-needed features such as multiple configurations, correct filename parsing, etc. Or at least so it seems.</p>
<p>As soon as I start digging into it it&rsquo;s very clear that <a href="http://www.boost.org/doc/html/bbv2.html">BoostBuild is much more complex than Jam</a>. It&rsquo;s not like Jam was a walk in the park, but BoostBuild is close to unacceptable. I&rsquo;ll take a Makefile any day of the week. Still, I would be willing to overlook that, bury myself deep in the documentation, and learn the system inside out if BoostBuild lived up to expectations: Jam speed with more features.</p>
<p>Unfortunately it doesn&rsquo;t. It doesn&rsquo;t just fall short either, it misses by several miles and destroys a friendly nearby town in the process. BoostBuild was the slowest of all the build systems I tested. Slower even than Scons! Talk about taking something small and fast and turning it into a slow, lumbering beast.</p>
<p>On the up side, I won&rsquo;t have to spend months learning the overly complex system. I had to find a silver lining somewhere, right?</p>
<p>Is <a href="http://www.boost.org/tools/build/v1/build_system.htm">BoostBuild v1</a> any better? It could be. But frankly, after my experience with v2 I wasn&rsquo;t in the mood to go check it out. Besides, it sounds like they&rsquo;re going to phase it out. If I want a fast, dead build system, I&rsquo;ll choose plain Jam.</p>
<h4 id="microsoft-visual-studio-2005">Microsoft Visual Studio 2005</h4>
<p><img alt="pyramids" loading="lazy" src="/the-quest-for-the-perfect-build-system-part-2/images/pyramids.jpg"> I had heard (from the comments in the previous articles and other posts on the internet) that <a href="http://msdn.microsoft.com/vstudio/">Visual Studio 2005</a> had an improved build system. Even though it seems that C++ is getting the shaft and not being rolled in the <a href="http://lab.msdn.microsoft.com/vs2005/teams/msbuild/default.aspx">MSBuild</a> system for this release, apparently it was still improved somewhat. Since a beta version of Visual Studio 2005 fell in my lap at the GameFest conference earlier this year, I decided to give it a try.</p>
<p>Incremental build times were definitely improved, although they are still far from Jam times. The one-second delay for each project is reduced to a bit less than half a second. Better for sure, but I don&rsquo;t see why it can&rsquo;t be faster. Still, that&rsquo;s getting in the range of being more usable.</p>
<p>One interesting addition is that, by default, Visual Studio 2005 will use multiple threads to compile C++ code. That will be a very welcome addition for full builds. Now I really need a quad-processor machine for our build server.</p>
<h4 id="vcbuild">VCBuild</h4>
<p>MSBuild, the Ant clone that Microsoft has been hailing as the next great thing to come, doesn&rsquo;t yet support C++ builds. It&rsquo;s a matter of priorities, I suppose. In the meanwhile, MSBuild will use the standalone <a href="http://www.gotdotnet.com/team/cplusplus/">VCBuild tool</a> to compile Visual Studio solutions.</p>
<p>VCBuild promises to be a lightweight, command-line version of devenv.com, ideally suited for build servers. Indeed, VCBuild had slightly better build times than MSVC2005, which is a huge improvement over 2003. That actually puts VCBuild as the fastest build system after Jam and Make.</p>
<p>At this point, I was interested enough to think about starting to use VCBuild for all of our command-line builds (at the server and the quick verification build before submitting code). Unfortunately, I immediately ran into a couple of problems. The first one is clearly listed in the Readme, so I knew it was coming: VCBuild will not add a dependent project to the link list like MSVC does. This is actually a <strong>good</strong> thing. I always hated that dependencies implied linking in Visual Studio. Unfortunately, since that&rsquo;s the default behavior, we are relying on it :-( It&rsquo;s easy to change, but it&rsquo;s just one small obstacle in the way.</p>
<p>The more serious problem was that VCBuild didn&rsquo;t seem to parse all the project settings correctly (warning levels for example), so it created very different results than a build with devenv.com.</p>
<p>Finally, I was disappointed to see that VCBuild does not support multiple processors. I had started thinking of VCBuild as a standalone MSVC2005 project compiler, but that&rsquo;s clearly not the case.</p>
<h4 id="fast-solution-build-msvc-plugin">Fast Solution Build MSVC plugin</h4>
<p>This one isn&rsquo;t really a standalone build system like the others covered in this article. However, it directly addresses the problem of speeding up Visual Studio builds, so it was worth including it in. In the past, I had very mixed experiences with it, but after hearing some really good things about it from some co-workers, I decided to give it a whirl.</p>
<p>As promised, <a href="http://www.workspacewhiz.com/FastSolutionBuild/FastSolutionBuildReadme.html">Fast Solution Build</a> does speed up incremental Visual Studio builds to speeds similar to Visual C++ 6.0. That is to say, doing an incremental build with no changes on a large solution takes about a second, which is really how it should be. This time around, I didn&rsquo;t have any problems with strangely broken builds or anything, so it seems pretty stable.</p>
<p>Unfortunately, Fast Solution Build is not without its set of problems. The first few problems are relatively minor. It doesn&rsquo;t seem to play well at all with C#. If I ever make the mistake of attempting a fast build on a C# project, Visual Studio will start a build and never end. The only way to get out of that state is to kill the process and restart Visual Studio. I guess I just need to train my fingers not to press F7 in C# projects.</p>
<p>The other problem is more of a user problem than anything related to the plugin. In spite of its name, Fast Solution Build, it does <strong>not</strong> build a solution, but it builds the selected project. That alone caused more problems than anything because most people are used to doing solution builds, not project builds. It&rsquo;s especially problematic if you want to have several unrelated projects build simultaneously (like in the case of unit tests projects and a game executable in addition to the libraries they depend on). More than once, we ended up checking in code that seemed to build fine, but broke when the server built the full solution.</p>
<p>The lack of a command-line interface also kills Fast Solution Build as a long-term solution. It might be OK while you&rsquo;re working with the IDE, but you can&rsquo;t use it for any command-line builds such as in the build server or for a quick sanity check we have before committing any code.</p>
<p>However, the biggest problem of all with Fast Solution Build is that it&rsquo;s just a plugin to Visual Studio, so you&rsquo;re left with many of the problems in Visual Studio itself, such as being hard to set up large solutions with lots of dependencies, having the visual representation mixed in with the real dependencies, suspect dependency checking (try deleting a file and then doing a build), or being tied to a single platform.</p>
<p>All in all, if you want a quick fix to your build times, Fast Solution Build is a good temporary band-aid provided you don&rsquo;t work with C# much and you don&rsquo;t have very complex solutions.</p>
<h4 id="scons">Scons</h4>
<p>As I was wrapping up the new measurements, I noticed the announcement in for the new version <a href="http://www.scons.org/">Scons</a> (0.96.91 pre-release). Since the last version was many moons ago, and since there was talk about improving Scons&rsquo; performance, I decided to give it a try.</p>
<p>The new version is indeed faster, but only by a tiny amount. Scons still lags far, far behind the curve in terms of performance. Unless the developers manage to squeeze performance improvements of several orders of magnitude, it&rsquo;ll remain unusable as a build system for fast iterations.</p>
<h4 id="ant">Ant</h4>
<p><img alt="skyscraper" loading="lazy" src="/the-quest-for-the-perfect-build-system-part-2/images/skyscraper.jpg"> <a href="http://ant.apache.org/">Ant</a> is one of the build systems I consciously left out of my first roundup. I had used it a bit in a build server, but I had the impression it was mostly intended as a &ldquo;build sequencer,&rdquo; with high-level actions like archiving files or emailing, and intended for full, nightly builds, rather for fast C++ incremental builds. It turns out that even though Ant was developed primarily with Java development in mind, it <a href="http://ant-contrib.sourceforge.net/cc.html">does have C++ support</a> through some of the extra <a href="http://ant-contrib.sourceforge.net/">contribution tasks</a>, with full dependency checking.</p>
<p>Another fact that put me off a bit from trying Ant was <a href="http://ant.apache.org/manual/using.html#example">its level of verbosity</a>. Writing XML files is anything but fun, and I much prefer the terseness of a Make file than the verbosity of an Ant file. Still, if a tool does the job well, I&rsquo;ll put up with a lot.</p>
<p>Ant&rsquo;s dependency checking was not bad, but not great either. Incremental build times with Ant were a bit worse then MSVS2005, but not by much. Frankly, that&rsquo;s faster than I expected with my initial preconceptions.</p>
<p>Full build times on Windows were blazingly fast. So much so, that I was convinced I had configured something wrong and I was only doing half the build. It turns out that everything was fine, but Ant will send all cpp files to be compiled to the compiler at once, whereas other build systems will process them one at a time. Under Linux with gcc, this doesn&rsquo;t make much of a difference, but in Windows using the MSVC compiler, it makes a huge difference. Other build systems should take note of that and take batching much more seriously.</p>
<h4 id="nant">Nant</h4>
<p><a href="http://nant.sourceforge.net/">Nant</a> is Ant&rsquo;s evil twin written with the .Net framework instead of Java. Frankly, I don&rsquo;t really see the point of Nant when Ant is already a mature project and runs in many more platforms. To make matters worse, the Nant developers decided to make their syntax different from Ant. Was that really necessary? If at least it were a straight Ant clone, it would be easier to migrate from one to the other. Personally, I would have preferred to see all that energy put into improving Ant instead of creating a .Net clone.</p>
<p>Having said that, one of the early surprises of Nant was <a href="http://nant.sourceforge.net/release/latest/help/tasks/cl.html">its native support for C++ compilation</a>. In Ant it was a custom task, here it works out of the box.</p>
<p>Nant also has a good set of <a href="http://nantcontrib.sourceforge.net/release/latest/help/tasks/index.html">extra contributed tasks</a>, including support for Perforce operations (although for a lot of the operations I wanted to do, I ended up having to fall back to command-line scripts because the tasks didn&rsquo;t have enough parameters or support for exactly what I wanted to do).</p>
<p>Another potentially interesting feature of Nant is <a href="http://nant.sourceforge.net/release/latest/help/tasks/solution.html">support for Visual Studio solution files</a>. This could be very useful because it would move the dependency checking out of Visual Studio and into Nant. Unfortunately, I tried running it on the solutions at work and it failed miserably. It seems that lots of compiler options are not parsed correctly, so it was impossible to build our existing solutions. I also suspect that C++ isn&rsquo;t their main target, so C++ project support is probably lagging behind C# and Visual Basic. Although I didn&rsquo;t try it, I imagine that Nant would choke at trying to build an Xbox 360 solution file.</p>
<p>Just for kicks, I tried running it on Linux with Mono, but apparently it only works with the Microsoft cl.exe compiler, not with gcc.</p>
<p>Build times were almost identical to those of Ant. Nant does very good batching as well, so full builds were blazingly fast, but incremental builds were only middle-of-the-road.</p>
<h4 id="rakerant">Rake/Rant</h4>
<p>I don&rsquo;t do any <a href="http://www.ruby-lang.org/en/">Ruby</a> development, so I had never heard of <a href="http://rake.rubyforge.org/">Rake</a> until Ivan-Assen Ivanov told me about it. In for a penny, in for a pound, so I went ahead and ran the tests on Rake as well.</p>
<p>Rake is a build system written in Ruby (and I assume mostly intended for Ruby users as well). Like Scons, it brings the full power and expressiveness of a scripting language (Ruby in this case) to the build script. It looks pretty simple and clean. The Ruby syntax is a bit strange at first sight, but it&rsquo;s easy to get used to (especially with lots of examples).</p>
<p>Unfortunately, Rake doesn&rsquo;t have C++ dependency checking built in. I could have probably cobbled something together with makedepend, but that would take more Ruby-foo than I&rsquo;m comfortable with.</p>
<p>Of course, all of this being open source, somebody, somewhere has had the same itch to scratch, and <a href="http://make.rubyforge.org/">Rant</a> was born. Apart from the cool name (after all, who doesn&rsquo;t like to write <a href="http://make.rubyforge.org/files/doc/rantfile_rdoc.html">Rantfiles</a>?), Rant looks very similar to Rake. Don&rsquo;t be fooled by their parallels to Make and [N]Ant. It&rsquo;s much more Make meets Scons in Rubyland than a derivative of Ant.</p>
<p>One feature of Rant that I really liked was the good support for error messages. If the Rantfile had a problem in it, it would correctly identify the problem and point me to it. After working with Ant/Nant, that was a welcome change.</p>
<p>The build times were a bit of a mixed bag. Full incremental builds were pretty good, definitely in the top third of the build systems I looked at. Unfortunately, building a single library without any changes was extremely slow. It seems that Rant had to do a lot of work before it could even look at an individual library. If it weren&rsquo;t because of that, I would be a lot more excited about it.</p>
<h4 id="make-and-msvc2003">Make and MSVC2003</h4>
<p>Nothing new in this front. For details, just read the <a href="/the-quest-for-the-perfect-build-system/">first article</a>. Everything there still applies.</p>
<h3 id="the-method">The Method</h3>
<p>I used the <a href="/the-quest-for-the-perfect-build-system/">same test case and hardware as the last time</a>. As a quick recap, the source code was made up of 50 static libraries with 100 classes each (2 files per class), 15 includes per cpp file to other files in that library, and 5 includes to files in other libraries.</p>
<p>The <a href="/wp-content/uploads/bin/generate_libs.zip">Python script</a> generates a tree with a full code base for every build system along with all the necessary build files. Whenever the build files for two platforms are different, two separate trees are created. Thanks to Jim Tilander to writing the Python scripts to generate the BoostBuild files.</p>
<p>The computer was a P4 2.8GHz CPU with 1GB of RAM and a 7200 rpm hard drive. The Linux distro was Mandrake Linux 10.2 with the 2.6 kernel and Windows XP (without any antivirus running&ndash;which makes a huge difference!).</p>
<p><a href="/wp-content/uploads/bin/generate_libs.zip"><img alt="icon" loading="lazy" src="/the-quest-for-the-perfect-build-system-part-2/images/script.png"> generate_libs.zip</a></p>
<h3 id="the-results">The Results</h3>
<p>Linux with gcc 3.4.1</p>
<table>
	<thead>
			<tr>
					<th>Build system</th>
					<th>Full build</th>
					<th>Incremental</th>
					<th>Incremental lib</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>GNU Make (3.80)</td>
					<td>2m 21s</td>
					<td>0m 2.4s</td>
					<td>0m 0.0s</td>
			</tr>
			<tr>
					<td>Jam (2.5)</td>
					<td>2m 42s</td>
					<td>0m 1.6s</td>
					<td>0m 0.1s</td>
			</tr>
			<tr>
					<td>BoostBuild v2 (3.1.10)</td>
					<td>3m 28s</td>
					<td>0m 46s</td>
					<td>0m 1.6s</td>
			</tr>
			<tr>
					<td>Scons (0.96.91 pre-release)</td>
					<td>5m 08s</td>
					<td>1m 06s</td>
					<td>0m 10.4s</td>
			</tr>
			<tr>
					<td>Ant (1.6.5)</td>
					<td>2m 8s</td>
					<td>0m 21s</td>
					<td>0m 1.7s</td>
			</tr>
			<tr>
					<td>Rant (0.4.4)</td>
					<td>2m 32s</td>
					<td>0m 10s</td>
					<td>0m 4.9s</td>
			</tr>
	</tbody>
</table>
<p><img alt="linux full builds" loading="lazy" src="/the-quest-for-the-perfect-build-system-part-2/images/linux_full.png"></p>
<p><img alt="linux inc builds" loading="lazy" src="/the-quest-for-the-perfect-build-system-part-2/images/linux_incremental.png"></p>
<p>Windows XP with MSVC 2003 compiler (except for the MSVC2005 run).</p>
<table>
	<thead>
			<tr>
					<th>Build system</th>
					<th>Full build</th>
					<th>Incremental</th>
					<th>Incremental lib</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Microsoft Visual Studio 2003</td>
					<td>7m 28s</td>
					<td>0m 54s</td>
					<td>0m 4s</td>
			</tr>
			<tr>
					<td>Microsoft Visual Studio 2003 + FastSolutionBuild</td>
					<td>7m 26s</td>
					<td>0m 1s</td>
					<td>0m 1s</td>
			</tr>
			<tr>
					<td>Microsoft Visual Studio 2005</td>
					<td>6m 46s</td>
					<td>0m 20s</td>
					<td>0m 3.5s</td>
			</tr>
			<tr>
					<td>VCBuild (7.10.3088.1)</td>
					<td>6m 56s</td>
					<td>0m 18s</td>
					<td>0m 0.5s</td>
			</tr>
			<tr>
					<td>Jam (2.5)</td>
					<td>6m 52s</td>
					<td>0m 3.1s</td>
					<td>0m 0.3s</td>
			</tr>
			<tr>
					<td>BoostBuild v2 (3.1.10)</td>
					<td>12m 03s</td>
					<td>0m 55s</td>
					<td>0m 2s</td>
			</tr>
			<tr>
					<td>Scons (0.96.91 pre-release)</td>
					<td>7m 52s</td>
					<td>0m 57s</td>
					<td>0m 7s</td>
			</tr>
			<tr>
					<td>Ant (1.6.5)</td>
					<td>3m 42s</td>
					<td>0m 33s</td>
					<td>0m 1.9s</td>
			</tr>
			<tr>
					<td>Nant (0.85)</td>
					<td>3m 24s</td>
					<td>0m 35s</td>
					<td>0m 1.4s</td>
			</tr>
			<tr>
					<td>Rant (0.4.4)</td>
					<td>5m 47s</td>
					<td>0m 25s</td>
					<td>0m 14s</td>
			</tr>
	</tbody>
</table>
<p><img alt="win full builds" loading="lazy" src="/the-quest-for-the-perfect-build-system-part-2/images/win_full.png"></p>
<p><img alt="win inc builds" loading="lazy" src="/the-quest-for-the-perfect-build-system-part-2/images/win_incremental.png"></p>
<p><em>Update:</em> Since several people asked, I timed Scons with MD5 checksum checking turned off in the hopes of getting a better time. I followed the advice described <a href="http://www.scons.org/cgi-bin/wiki/GoFastButton">here</a>. Just like last time, turning off MD5 checksum made it go <em>slower</em> if that makes any sense.</p>
<table>
	<thead>
			<tr>
					<th>Scons build (Linux)</th>
					<th>Incremental build time</th>
					<th>Difference</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Normal</td>
					<td>1m 06s</td>
					<td>--</td>
			</tr>
			<tr>
					<td>--max-drift=1</td>
					<td>1m 10s</td>
					<td>+5s</td>
			</tr>
			<tr>
					<td>--implicit-deps-unchanged</td>
					<td>0m 47s</td>
					<td>-19s</td>
			</tr>
			<tr>
					<td>--max-drift=1 &ndash;implicit-deps-unchanged</td>
					<td>0m 50s</td>
					<td>-16s</td>
			</tr>
	</tbody>
</table>
<p>Using the option to indicate unchanged dependencies made it go a bit faster, but that&rsquo;s not an option we can realistically use during development, since that would be changing constantly with the structure of our program. Still, the fact that without doing any dependency checking it&rsquo;s still taking 47 seconds. What is it doing??</p>
<p>With multiprocessor machines being so common these days, a good build system needs to support parallel execution of tasks in multiple processors. Surprisingly, not all of the build systems compared here support it. Of the usable build systems, only Make, Jam, and MSVC2005 actually support parallel builds.</p>
<table>
	<thead>
			<tr>
					<th>Build system</th>
					<th>Multiprocess builds</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>GNU Make</td>
					<td>Yes</td>
			</tr>
			<tr>
					<td>Microsoft Visual Studio 2003</td>
					<td>No</td>
			</tr>
			<tr>
					<td>Microsoft Visual Studio 2005</td>
					<td>Yes</td>
			</tr>
			<tr>
					<td>VCBuild</td>
					<td>No</td>
			</tr>
			<tr>
					<td>Jam</td>
					<td>Yes</td>
			</tr>
			<tr>
					<td>BoostBuild v2</td>
					<td>Yes</td>
			</tr>
			<tr>
					<td>Scons</td>
					<td>Yes</td>
			</tr>
			<tr>
					<td>Ant</td>
					<td>No</td>
			</tr>
			<tr>
					<td>Nant</td>
					<td>No</td>
			</tr>
			<tr>
					<td>Rant</td>
					<td>No</td>
			</tr>
	</tbody>
</table>
<h3 id="conclusion">Conclusion</h3>
<p>Jam still remains the best-performing build system of all by quite a lot. Unfortunately, the total lack of support and community around it make it very difficult to recommend. There has been some talk recently in the <a href="http://lists.midnightryder.com/listinfo.cgi/sweng-gamedev-midnightryder.com">sweng-gamedev</a> mailing list to do some work for build systems. Maybe we could take over the continued development of Jam. If that happened, I wouldn&rsquo;t hesitate to recommend it. Until then, unless you&rsquo;re a Jam expert or are willing to dig through user-created patches in the <a href="http://public.perforce.com/public/index.html">Perforce Public Depot</a>, Jam is not a realistic option.</p>
<p>MSVS2005 has improved a lot from 2003, and along with VCBuild, it&rsquo;s one of the best performing build systems under Windows for incremental links. Personally, I hate to be locked in to proprietary tools and single platforms, so I would opt for the next best systems, which are Ant/Nant. Pick your flavor of choice, they&rsquo;re about the same.</p>
<p>MSBuild can be promising, especially once Microsoft rolls out their <a href="http://www.microsoft.com/xna/3.7.2005.aspx">XNA Studio</a> extensions specifically designed for asset building. It&rsquo;ll only run in Windows, but at least they claimed that they&rsquo;re making it general enough you can use for building any type of assets, not just their own formats. That&rsquo;s definitely one to watch for the future.</p>
<p>If you&rsquo;re comfortable with Make files, it still remains as a great option for very fast builds. You&rsquo;ll probably want to wrap Make in a more comprehensive build system (such as Ant) for your build server, packaging builds, etc. But Make can be your everyday workhorse during development.</p>
<p>Whatever you do, stay far, far away from BoostBuild and Scons. Their performance is simply so horrible there&rsquo;s no excuse to use them unless build times are of no importance to you at all.</p>
<p>I remain hopeful that we might be able to resurrect Jam. If you&rsquo;re interested in contributing, contact me through email, comments on this page, or participate in the sweng-gamedev discussion directly</p>
<p><a href="/wp-content/uploads/bin/generate_libs.zip"><img alt="icon" loading="lazy" src="/the-quest-for-the-perfect-build-system-part-2/images/script.png"> generate_libs.zip</a></p>]]></content:encoded></item><item><title>The Quest for the Perfect Build System</title><link>https://gamesfromwithin.com/the-quest-for-the-perfect-build-system/</link><pubDate>Mon, 06 Jun 2005 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/the-quest-for-the-perfect-build-system/</guid><description>&lt;p&gt;First there were punch cards, and people somehow managed to write software. Then came interactive computing with mainframes and personal computers, and people wrote even more software and become even more productive. There is no doubt that our development environments today are light-years ahead of what the computer pioneers had half a century ago. Yet I constantly see projects suffer with horrible environments that force slow iteration cycles on programmers.&lt;/p&gt;</description><content:encoded><![CDATA[<p>First there were punch cards, and people somehow managed to write software. Then came interactive computing with mainframes and personal computers, and people wrote even more software and become even more productive. There is no doubt that our development environments today are light-years ahead of what the computer pioneers had half a century ago. Yet I constantly see projects suffer with horrible environments that force slow iteration cycles on programmers.</p>
<p>I define an iteration cycle as the time elapsed between making a trivial change and being able to see the results of that change. In particular I&rsquo;m concentrating on large-scale (around one million lines of code) C++ projects, which is representative of modern PC and console games today.</p>
<p>Of course, there&rsquo;s more to fast iteration than just the speed of the build system. How quickly you&rsquo;re able to get in the game and see the results is a big factor (another reason why I wouldn&rsquo;t want to live without unit tests). The <a href="/physical-structure-and-c-part-1-a-first-look/%20">physical dependencies</a> of your program are going to affect how quickly your code builds. And if you&rsquo;re always working with a full game executable that takes forever to link, your iteration times are going to be shot (yet another reason to use unit tests!).</p>
<p>But let&rsquo;s put that aside and concentrate on the build system itself.</p>
<p>Fast iteration is more than just about time and speed. It&rsquo;s also about how you feel about the code and what you dare do with it. When things are slow and painful, you&rsquo;re going to be a lot less likely to try new things, or fix one last thing to clean up the code, or refactor something out of a header file into its own module. Over time, this is going to accumulate into cruft, hacks, and unmaintainable code. It&rsquo;s also about not breaking up the <a href="http://c2.com/cgi/wiki?MentalStateCalledFlow">flow</a>, the mental state you&rsquo;re in while you&rsquo;re writing software. Interruptions of more than just a few seconds are much more detrimental than their time value alone.</p>
<p><img alt="construction" loading="lazy" src="/the-quest-for-the-perfect-build-system/images/construction_2.jpg"> When you add <a href="/stepping-through-the-looking-glass-test-driven-game-development-part-1/">test-driven development</a> to the mix, fast iteration becomes even more crucial. With test-driven development, you end up doing micro-cycles of modify-compile-test, sometimes several times per minute. Unless you have very fast build times, you&rsquo;re dead in the water.</p>
<p>Before we go any further, let&rsquo;s crunch a few numbers. It&rsquo;s not so much to show specific improvements, but to have as a reference point going forwards. Think about the project you&rsquo;re currently working on. How long does it take to build when you modify a single cpp file (or even no files at all)? I&rsquo;ve seen projects that took over two minutes to build, and anywhere between 30 seconds to one minute is fairly typical. Let&rsquo;s say 30 seconds for this example. How often do you need to do a build? It&rsquo;s not very fast, so maybe once every 5 minutes, 8 hours a day. That adds up to a staggering 48 minutes per day, or 10% of your full work day!</p>
<p>Now reduce the build time to two seconds instead. And to make things more interesting, let&rsquo;s do a build every two minutes. That adds up to be 8 minutes per day, and, most importantly, they feel like almost instant builds, so they don&rsquo;t bring you out of the flow state. That&rsquo;s what our goal should be for a build system.</p>
<h3 id="the-goals">The Goals</h3>
<p>As I started looking into different build systems (there are a lot of them out there!), I noticed that they have very different sets of goals, and a lot of them are fairly irrelevant to my particular needs.</p>
<p>As a game developer, I work with a varied, but limited number of platforms (most of which are not supported out of the box by build tools anyway). I&rsquo;m also not planning on releasing the source code any time soon to let players compile the game in any platform, so I have no need to have a build system that automatically detects all the correct settings and does the right thing for any possible platform.</p>
<p>Some other build systems had useless features built in, such as access to version control or the ability to send emails. I consider those type of tasks to be totally beyond what the core build system should do, and I prefer to have those features in a wrapper system that does build/test/deployment of builds by calling the build system itself.</p>
<p>So what exactly do I want in a build system?</p>
<ul>
<li>Super-fast incremental builds (around two seconds). This is the key to fast iteration and I want this at almost any cost.</li>
<li>Customizable. I&rsquo;m going to be using unusual compilers and environments. I want to be able to easily set my own rules and actions and not be tied to any particular platform or compiler.</li>
<li>Correctness. I want the build system to build the minimal amount of files and still do the right thing under most normal circumstances.</li>
<li>Multiprocessor support. I also care about the speed of a full build, and with multiprocessor machines finally becoming popular, using multiple processors is a great way to speed up build times.</li>
<li>Scalable. I want all the related source code to be tied to the same build system. I don&rsquo;t want to create a separate build file for every minor tool so they build at a reasonable speed. I&rsquo;d like to simply build any target and have the minimal amount of files rebuilt.</li>
</ul>
<h3 id="the-contenders">The Contenders</h3>
<p><strong>Visual Studio .NET</strong></p>
<p>Most game developers doing Windows or Xbox development will be familiar with this build system. I&rsquo;ve been stuck with it for many years, and while things were not great in Visual Studio 6.0 and earlier versions, it became decidedly unusable when it turned into &ldquo;.NET&rdquo;. I don&rsquo;t know what happened, but I suspect that in their effort to cram all those languages under a single IDE they crippled the C++ build system even more.</p>
<p>My main gripe is how slow Visual Studio .NET is when doing an incremental build on a solution with many projects. It&rsquo;s roughly a second per project. If you have 50 projects, there goes a full minute for nothing. That&rsquo;s simply unacceptable, so I&rsquo;ve always had to work around it by creating many solutions with the minimum amount of projects necessary, or keeping the dependencies in my head and forcing builds by hand. Alternatively you could throw all the code in a couple of projects instead of breaking it up into many different ones, but that&rsquo;s like jumping off a cliff to avoid being stung by a bee.</p>
<p>Because Visual Studio mixes the build system with the visual representation of the files, large solutions are not only slow to build, but are a positive pain to work with, making browsing the source code extremely difficult.</p>
<p>The problems with Visual Studio don&rsquo;t end there. The solution and project files are a pain to generate, they&rsquo;re full of magical GUIDs and references to the registry, and they&rsquo;re extremely verbose. The .NET framework offers an API to create those files, but the fact remains that they&rsquo;re much more complex to create than any of the other build systems.</p>
<p>If you don&rsquo;t generate the project files by hand, you soon enter configuration hell. Anybody who&rsquo;s had to make sweeping changes to lots of projects with multiple configurations through the IDE will know what a painful process I&rsquo;m talking about.</p>
<p>Some of my other complaints are not being able to easily set the build order for different projects (it appears to be determined by the order in which they appear in the solution file), or the fact that setting a dependency between two projects forces an implicit linking.</p>
<p>All in all, Visual Studio seems very well suited to small, toy projects. Projects with just a couple of libraries and a few thousand lines. Anything bigger than that and it becomes an exercise in frustration.</p>
<p>On the bright side, it is possible to use &ldquo;makefile projects&rdquo; in Visual Studio, which completely bypasses Visual Studio&rsquo;s own build system and simply calls an external command to build the project. Visual Studio also offers a command-line line interface, so at least it is possible to do builds from the command line without launching the IDE. Finally, there are some <a href="http://www.workspacewhiz.com/FastSolutionBuild/FastSolutionBuildReadme.html">third-party plug-ins</a> that can speed up the dependency checking, which can help with some of the problems (unfortunately, FastSolutionBuild doesn&rsquo;t seem to have a command-line interface, which renders it useless for my needs).</p>
<p>Other third-party add-ons like <a href="/how-incredible-is-incredibuild/">Incredibuild</a> claim to speed up full builds, but they do so at the expense of incremental build speed, which I consider much more important.</p>
<p><strong>Make</strong></p>
<p>Make is the granddaddy of all the build systems. With a distinguished history of over 20 years, it has certainly proved its worth in the real world by building hundreds of thousands of projects over the years.</p>
<p>But make is <a href="http://www.scons.org/cgi-bin/wiki/FromMakeToScons">far from perfect;</a> otherwise there would be no need for other build systems. However, things are not as bad as people make them out to be, especially with modern versions of make (<a href="http://www.gnu.org/software/make/">GNU make</a> for example). The lack of portability is not an issue for us because we can just trivially write a new makefile, or a variant, for every platform we support.</p>
<p>The claims about make not being scalable are more serious. The article <a href="http://www.canb.auug.org.au/~millerp/rmch/recu-make-cons-harm.html">&ldquo;Recursive Make Considered Harmful&rdquo;</a> certainly did much harm to make&rsquo;s reputation. Specifically, that paper claims that it&rsquo;s very hard to get the order of recursion right because using recursive make has no global project view. I think that&rsquo;s only true if you&rsquo;re dealing with self-modifying source code files or autogeneration of source code. If that&rsquo;s not the case, I can&rsquo;t see how the order of recursion can matter at all as long as the dependencies are met.</p>
<p>As for the claim that make is slow, let&rsquo;s put that off until we compare it to the other build systems.</p>
<p>Personally, I really like make. It&rsquo;s small, clean, and elegant. It does one thing and it does it very well. It&rsquo;s easy to extend and modify. At first I was surprised that make didn&rsquo;t do implicit dependency checking of C files (building a C file when an included header file changes), but it fits perfectly with the simplicity of make. It&rsquo;s just a dependency graph with actions. If you don&rsquo;t tell it about a rule, it won&rsquo;t know about it. Fortunately, we can use tools like <a href="http://www.xfree86.org/current/makedepend.1.html">makedepend</a> to generate the C dependencies with extreme ease.</p>
<p>One of my only gripes with main is the silly tab syntax. The fact that action commands have to be preceded by a tab character is awkward and out of place today, but it&rsquo;s a small quirk I&rsquo;m willing to adapt to. Fortunately gnu make&rsquo;s error messages are very clear and it even asks &ldquo;Did you forget to put a tab before the command?&rdquo;</p>
<p><strong>Jam</strong></p>
<p><img alt="construction" loading="lazy" src="/the-quest-for-the-perfect-build-system/images/construction_1.jpg"> <a href="http://www.perforce.com/jam/jam.html">Jam</a> was born an an improved make. It tried to keep all the good things about make and fix all the problems. And to a large extent, it succeeded.</p>
<p>Like make, Jam is small and easily portable. It deals better with inter-project dependencies by avoiding recursive Jam invocations (while still allowing individual sections to be built separately). The Jam language, even though it&rsquo;s still fairly restrictive, is more expressive than make and it&rsquo;s easier to write complex functionality.</p>
<p>One of the main differences from make is that Jam actually provides a fair amount of base functionality in its Jambase file. Jam out of the box knows about some of the most popular development environments and languages (including implicit dependency checking for C/C++ files), so it simplifies the build files for the simple cases. In the other cases, you can add your own rules and actions very easily.</p>
<p>I find it funny that while Jam fixes make&rsquo;s weird tab requirement, it adds its own &ldquo;space semicolon&rdquo; weird command terminator (although I know some programmers who think that &ldquo;space semicolon&rdquo; is the one and true way). Either way, it really doesn&rsquo;t matter since it&rsquo;s such a small thing.</p>
<p>Jam also has spawned some forks that add extra functionality but are fully backwards compatible: <a href="http://freetype.sourceforge.net/jam/">FTJam</a> and <a href="http://www.boost.org/tools/build/jam_src/">BoostJam</a>.</p>
<p><strong>Scons</strong></p>
<p><a href="http://www.scons.org/">Scons</a> has been hailed as the next step in the evolution of build systems. It is supposed to be a much improved make-like system, not only written in Python, but using Python as the language used to define the build itself. Python is a fully general, object-oriented language, so it&rsquo;s extremely expressive. It also has the advantage of being a well-established language with a great set of documentation, debuggers, and tools, which can make creating and debugging complex build scripts easier.</p>
<p>Scons also claims to be extremely accurate when it comes to determining what files need to be built. It doesn&rsquo;t rely in the time stamp for a file, but it uses the MD5 signature instead (a type of checksum approach). Another very intriguing feature I didn&rsquo;t get around to testing is the network cache of built object files.</p>
<p>Walking into this test I was a bit afraid of what I might find. I had read some reports of several people having problems with Scons performance on large data sets. However, the latest version (0.96.90), released just a couple of months ago, is supposed to have some performance improvements.</p>
<h3 id="the-method">The Method</h3>
<p>As a test, I decided to run each of the different build systems on the same codebase. Instead of using some real-world codebase, with its own set of quirks and problems (and the difficulty of easily building it with the different systems), I wrote <a href="/wp-content/uploads/bin/generate_libs.py">a script</a> to generate a simple C++ codebase. The code structure is based on what I expect to see in my own projects with many different projects. The physical dependencies in the generated codebase are extremely well contained, and header files never include other header files. Real code bases would have more complicated dependencies and would make the tendencies we see here even more exaggerated.</p>
<p>The specific parameters I used for this test were:</p>
<ul>
<li>50 static libraries</li>
<li>100 classes (2 files per class, .h and .cpp) per library</li>
<li>15 includes from that library in each class</li>
<li>5 includes from other libraries in each class</li>
</ul>
<p>This is by all accounts still a small or at most medium-sized codebase. A full game engine and tools can easily become much larger than this.</p>
<p>Thinking back, I really should have done the test with at least 100 libraries, not 50, because all my libraries have an extra associated project for unit tests. No big deal. I don&rsquo;t think it would have changed the results very much. The important thing was to get enough code to make measurements noticeable (if we just build 10 files every build system is going to be really snappy).</p>
<p>For each of the build systems, I measured three operations:</p>
<ul>
<li>Full rebuild. Compiling the full source code for the first time. I didn&rsquo;t expect this time to change much at all from build system to build system or even across platforms. I was quite wrong!</li>
<li>Incremental build: Doing another build without any changes. This is the really interesting measurement that will tell us a lot about potential for fast iteration.</li>
<li>Incremental build on a single library: Doing a build of a library without any changes.</li>
</ul>
<p>I did the measurements in both Linux (2.6 kernel) and Microsoft Windows XP for different systems. Clearly some build systems only run in one platform (Visual Studio). But I decided to run some of the other build systems under Windows as well to provide a more fair comparison.</p>
<p>The specific hardware I ran these tests in is not as important since all we&rsquo;re comparing are their relative merits. But for the curious it&rsquo;s a P4 2.8 GHz CPU with hyperthreading, 2GB of fast RAM, and a 7200 rpm EIDE hard drive. The most important part is that I had enough memory to prevent thrashing.</p>
<p>GNU make, Jam, and Scons all support parallel builds. While it won&rsquo;t speed up incremental builds any, this can reduce the time for full builds dramatically. Since this test was done in a single-CPU machine (and the primary measure was incremental builds), I restricted all the builds to use a single process.</p>
<h3 id="the-results">The Results</h3>
<table>
	<thead>
			<tr>
					<th>System</th>
					<th>Compiler</th>
					<th>Platform</th>
					<th>Full build</th>
					<th>Incremental</th>
					<th>Incremental lib</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Visual Studio</td>
					<td>VC++</td>
					<td>Windows XP</td>
					<td>7m 28s</td>
					<td>0m 54s</td>
					<td>0m 4s</td>
			</tr>
			<tr>
					<td>Make</td>
					<td>g++</td>
					<td>Linux</td>
					<td>2m 21s</td>
					<td>0m 2.4s</td>
					<td>0m 0.0s</td>
			</tr>
			<tr>
					<td>Jam</td>
					<td>g++</td>
					<td>Linux</td>
					<td>2m 42s</td>
					<td>0m 1.6s</td>
					<td>0m 0.1s</td>
			</tr>
			<tr>
					<td>Jam</td>
					<td>VC++</td>
					<td>Windows XP</td>
					<td>6m 52s</td>
					<td>0m 3.1s</td>
					<td>0m 0.3s</td>
			</tr>
			<tr>
					<td>Scons</td>
					<td>g++</td>
					<td>Linux</td>
					<td>5m 31s</td>
					<td>1m 02s</td>
					<td>0m 16s</td>
			</tr>
			<tr>
					<td>Scons</td>
					<td>VC++</td>
					<td>Windows XP</td>
					<td>8m 02s</td>
					<td>0m 55s</td>
					<td>0m 8s</td>
			</tr>
	</tbody>
</table>
<p>We can make lots of very interesting observations from this table.</p>
<p>First of all, it confirms what I had seen all along, that Visual Studio is horrible for incremental builds with many projects. My off-the-cuff estimate of one second per project ended up being extremely accurate (54 seconds for 50 projects). That&rsquo;s simply not acceptable for me.</p>
<p>As I feared, Scons, failed the fast iteration test as well. It actually ended up being slower than Visual Studio in all accounts, even for individual library rebuilds. It might do the &ldquo;right&rdquo; thing under all conditions, but frankly, that&rsquo;s not a price I&rsquo;m willing to pay to get absolutely correct results. I really don&rsquo;t think I encounter any situation in everyday work in which Scons would do the right thing and make or Jam wouldn&rsquo;t.</p>
<p>At this point, I was afraid that I just wasn&rsquo;t going to be able to get the type of iteration I wanted out of file-based, compiled languages. Fortunately that&rsquo;s not the case. Both make and Jam do a great job and fall in the range of what I consider acceptable (around a couple of seconds).</p>
<p>There are two interesting observations to be made about full build times from the chart above. First of all, Scons with g++ under Linux is twice as slow as Jam or make for a full rebuild. I find that extremely surprising. Although I guess that&rsquo;s the extra minute of dependency checking plus some extra overhead of its own. I tried some of the <a href="http://www.scons.org/cgi-bin/wiki/SconsRecipes">suggestions to get faster Scons builds</a> (by trading off accuracy for speed), but they just improved incremental build times by a couple of seconds. Clearly, Scons needs to do some catching up before it can play with the big boys.</p>
<p>The other one is comparing g++/Linux with VC++/Windows XP. Jam is over twice as slow with VC++/Windows XP than it is with g++ under Linux. Is it Windows XP or is it Visual C++? I don&rsquo;t know. It would be interesting to try the experiment with g++ or some other compiler under Windows and see if the times are reduced at all. I suspect the Windows file system might have something to do with that.</p>
<h3 id="conclusion">Conclusion</h3>
<p>This little experiment cleared up a lot of doubts for me. I&rsquo;m ready to ditch Visual Studio as a build system and replace it completely with Jam or make. Make is a simpler but Jam probably edges it out because it&rsquo;s a bit nicer, it doesn&rsquo;t have any recursive problems, and the default functionality is pretty handy. It&rsquo;s hard to go wrong with either one.</p>
<p>Since most programmers still expect to work from within the Visual Studio IDE, you can easily create a &ldquo;makefile&rdquo; project type and hook it up to the build system of your choice.</p>
<p>One interesting idea that came up during this research in the <a href="http://scons.tigris.org/servlets/SummarizeList?listName=users">Scons mailing list</a> is that of a background process that monitors which files change and updates dependency graphs on the fly. So whenever you initiate a build, all the work has already been done and the build can start right away. A variation on this idea that has been brought up in some TDD mailing lists is that of the build system not just computing dependencies in the background, but actually attempting to compile the code and run the unit tests in the background. If any of the tests fail, they can even be highlighted in the source code editor. Sort of like an on-the-fly, smart code checker on steroids.</p>
<p>Of course, we could also choose a language that has much smaller build times. I haven&rsquo;t worked on a large-scale C# project yet, but the small tools I&rsquo;ve created have impressed me with how fast the iteration can be. The same can be said for scripting languages such as Python or Lua. Unfortunately, we&rsquo;re stuck with C++ for the foreseeable future in game development, so we better learn to deal with it the best we can.</p>
<p>For now, I&rsquo;ll be happy to stick with Jam and two-second incremental builds. Let&rsquo;s start jamming!</p>
<p><a href="/wp-content/uploads/bin/generate_libs_py.txt"><img alt="icon" loading="lazy" src="/the-quest-for-the-perfect-build-system/images/script.png"> generate_libs.py</a></p>
]]></content:encoded></item><item><title>The Care and Feeding of Pre-Compiled Headers</title><link>https://gamesfromwithin.com/the-care-and-feeding-of-pre-compiled-headers/</link><pubDate>Wed, 27 Apr 2005 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/the-care-and-feeding-of-pre-compiled-headers/</guid><description>&lt;p&gt;The great majority of the literature on warfare concentrates on topics such as formations, maneuvers, equipment, and training. What they often leave out is the importance of the supply lines. The most cunningly devised plan will be worthless in the long term if your supply lines fail.&lt;/p&gt;
&lt;p&gt;The same can be said for large-scale C++ development. Most of the books and articles out there deal with class hierarchies, object-oriented design, and mind-bending template tricks. However, when it comes down to it, a solid physical structure and good code layout will go a long way towards making all programmers productive. When the milestones near and the pressure piles on, a badly structured C++ codebase is likely to be as fatal as the cold, Russian winter was to Napoleon&amp;rsquo;s army.&lt;/p&gt;</description><content:encoded><![CDATA[<p>The great majority of the literature on warfare concentrates on topics such as formations, maneuvers, equipment, and training. What they often leave out is the importance of the supply lines. The most cunningly devised plan will be worthless in the long term if your supply lines fail.</p>
<p>The same can be said for large-scale C++ development. Most of the books and articles out there deal with class hierarchies, object-oriented design, and mind-bending template tricks. However, when it comes down to it, a solid physical structure and good code layout will go a long way towards making all programmers productive. When the milestones near and the pressure piles on, a badly structured C++ codebase is likely to be as fatal as the cold, Russian winter was to Napoleon&rsquo;s army.</p>
<p>I&rsquo;ve already written before about how important the physical layout of a codebase can be (<a href="/physical-structure-and-c-part-1-a-first-look/%20">[1]</a> and <a href="/physical-structure-and-c-part-2-build-times/%20">[2]</a>), so I&rsquo;m not going to go over it again. This is going to be about how to use one of the many tools at our disposal to make working with a large codebase more bearable: pre-compiled headers.</p>
<h3 id="benefits-and-drawbacks">Benefits and drawbacks</h3>
<p>The only benefit of pre-compiled headers is build speed. Nothing more, nothing less. But we&rsquo;re not talking about a measly 10-15% build speed improvement. Pre-compiled headers can easily improve build times by an order of magnitude or more depending on your code structure. Clearly, it&rsquo;s a technique worth exploring.</p>
<p>The major benefit is when doing full rebuilds, but it can also help when building individual files. So it will help with the bane of the C++ programmer: iteration time (it won&rsquo;t do anything to help with link times, though).</p>
<p>What&rsquo;s not to like about pre-compiled headers? Several things, it turns out:</p>
<ul>
<li>Using a single set of pre-compiled headers exposes more symbols than necessary for many modules. That can lead to increased physical and logical dependencies.</li>
<li>Modifying a header that is part of the pre-compiled headers set will trigger a full rebuild.</li>
<li>Pre-compiled headers are not supported in every environment (although these days most compilers seem to support them to some extent).</li>
<li>Bloated pre-compiled headers can slow things down. This drawback is only from hearsay and minor anecdotal personal evidence. It sort of makes sense (with the pre-compiled header file getting huge), but I would like to see some hard data. Has anybody measured this?</li>
</ul>
<p>What&rsquo;s the best way to deal with the drawbacks in order to be able to take full advantage of the super-speedy compile times?</p>
<h3 id="how-do-pre-compiled-headers-work">How do pre-compiled headers work?</h3>
<p><img alt="canon" loading="lazy" src="/the-care-and-feeding-of-pre-compiled-headers/images/napoleon-canon.jpg"> A C++ compiler operates on one compilation unit (cpp file) at the time. For each file, it applies the pre-preprocessor (which takes care of doing all the includes and &ldquo;baking&rdquo; them into the cpp file itself), and then it compiles the module itself. Move on to the next cpp file, rinse and repeat. Clearly, if several files include the same set of expensive header files (large and/or including many other header files in turn), the compiler will be doing a lot of duplicated effort.</p>
<p>The simplest way to think of pre-compiled headers is as a cache for header files. The compiler can analyze a set of headers once, compile them, and then have the results ready for any module that needs them.</p>
<p>I won&rsquo;t get into the specifics on how to set up pre-compiled headers; that&rsquo;s very environment-specific. You might want to start with Bruce Dawson&rsquo;s great article on <a href="http://www.cygnus-software.com/papers/precompiledheaders.html">pre-compiled headers on Visual C++</a>, or the GNU documentation on <a href="http://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html">pre-compiled headers with gcc</a>.</p>
<p>In very general terms, you need to specify one file (here we&rsquo;ll call it PreCompiled.h) as containing the pre-compiled headers. Anything included in that file will then become part of the pre-compiled headers cache. Then, you just need to make sure to include PreCompiled.h in each module you want to use the pre-compiled headers from. One word of warning: Visual C++ ignores all lines in the cpp file before #include &ldquo;PreCompiled.h&rdquo;, so it&rsquo;s a good habit to make sure that&rsquo;s the first line of code in each file.</p>
<h3 id="organizing-your-code">Organizing your code</h3>
<p>Unless you&rsquo;re dealing with very small code bases, you should really split up your code into multiple libraries. Not only will you get the most benefit from pre-compiled headers that way, but you&rsquo;ll reap <a href="/simple-is-beautiful/">a variety of other benefits</a>. Then set up each library with one set of pre-compiled headers.</p>
<p>The big question now is, what should go in the pre-compiled headers? You can put anything you want, really. But by observing a few simple guidelines, you can maximize your build times, which is what this is all about.</p>
<ul>
<li>Add &ldquo;expensive&rdquo; includes to the pre-compiled header file. &ldquo;Expensive&rdquo; headers are the ones that cause a cascade of other includes. Including these every time you compile a file can be quite time consuming. Some of the usual suspects are windows.h, STL headers, single includes for whole APIs, etc.</li>
<li>Add headers that are included from many different files, even if they&rsquo;re not very expensive. A header file that is included from 50 different files is almost as bad as a header file that is included once but causes 50 includes of its own. Actually, a simple file that is included in many cpp files is preferable to an expensive one included only once because recompiling one of those many cpp files is going to be fast even if the file is not in the pre-compiled headers, so iteration is still relatively fast.</li>
<li>Don&rsquo;t put any headers from the library itself in the pre-compiled headers. The only exception to this is if you have a header in your library that happens to be included everywhere (which is probably a sign that something is wrong anyway). Otherwise, every time you modify a header that was included in the pre-compiled headers file, you&rsquo;ll cause a full rebuild.</li>
</ul>
<p>So clearly, the best candidates to add to the pre-compiled header list are expensive includes that happen many times. Those are the ones that are going to get us the big speedup in build times.</p>
<p>At the same time, we don&rsquo;t want to blindly add every header used by our library. That will make regenerating the pre-compiled headers slightly slower, but, most importantly, will cause all the symbols in those headers to be available to the whole library, which is something undesirable if we&rsquo;re trying to keep dependencies to a minimum. There&rsquo;s also the potential issue of pre-compiled header bloat, but I need to confirm that.</p>
<p>Since those guidelines can be applied automatically, I decided to write <a href="/wp-content/uploads/bin/list_precomp.py">a script to report the headers that would most benefit from being in the pre-compiled headers</a> for a particular project. Instead of trying to parse the C++ code and find the chains of includes (which is not that hard but requires dealing with include paths, define statements, and almost implementing the full C pre-processor), the script uses the output of building the project with the option to show all includes (-H with gcc, /showincludes in Visual C++). The includes are conveniently formatted with indentation corresponding to the level at which they were included, so it&rsquo;s very easy for the script to determine which includes are expensive.</p>
<p>The script also accepts a string to ignore all includes which include that string in their path. That way you can easily eliminate includes from the library itself from being recommended to be part of the pre-compiled headers. Unfortunately, gcc outputs the relative path that was used to get to the include, which makes it harder to filter out specific libraries and might result in the same header being included in different ways. To prevent that, you might want to process the output first and automatically change all the paths to be absolute instead of relative (the script can&rsquo;t do it because there are no guarantees you&rsquo;re running it on the same platform as the build, let alone in the same directory of the same machine).</p>
<p>Right now the script can parse the output created from gcc and Visual C++, but it should be really easy to extend to any other compiler just by changing the regular expressions it uses to parse the include outputs.</p>
<p>As an example, I ran it the script on the output of building one of the libraries in our game engine at High Moon. These are the results:</p>
<pre tabindex="0"><code> Counting includes in includes.txt
 Cpp files:  38 (Header file, score, times included, includes caused by the header)
 (&#39;file1.h&#39;, 11590, 190, 60)
 (&#39;file2.h&#39;, 532, 532, 0)
 (&#39;file3.h&#39;, 401, 401, 0)
 (&#39;file4.h&#39;, 384, 4, 95)
 (&#39;file5.h&#39;, 330, 33, 9)
 (&#39;file6.h&#39;, 319, 11, 28)
 (&#39;file7.h&#39;, 228, 228, 0)
 (&#39;file8.h&#39;, 155, 155, 0)
 (&#39;file9.h&#39;, 151, 151, 0)
 (&#39;file10.h&#39;, 105, 35, 2)
 (&#39;file11.h&#39;, 105, 105, 0)
 (&#39;file12.h&#39;, 101, 101, 0)
</code></pre><p>Each include file is reported with a score, the number of times it is included in the program, and the number of other includes it causes. The score is the most important value about each file, which is simply the product of the number of times a file is included and the number of includes that file causes (plus one to take itself into account). So the higher the score, the more expensive an include is.</p>
<p>Interestingly, at the top of the list we have an extremely expensive include that should absolutely be added to the pre-compiled header list. That alone should make a significant positive impact in build times. The rest of the top files listed could be added, although their impact would be much lower.</p>
<p>As another example, I ran the script on the results of building my current mp3 player, <a href="http://amarok.kde.org/">Amarok</a>.</p>
<pre tabindex="0"><code> Counting includes in /usr/local/src/amarok-1.2.3/amarok/src/out.txt
 Cpp files:  764 (Header file, score, times included, includes caused by the header)
 (&#39;/usr/lib/qt3//include/qglobal.h&#39;, 46620, 630, 73)
 (&#39;/usr/lib/qt3//include/qmap.h&#39;, 3740, 110, 33)
 (&#39;/usr/lib/gcc/i586-mandrake-linux-gnu/3.4.1/../../../../include/c++/3.4.1/vector&#39;, 3182, 37, 85)
 (&#39;/usr/lib/qt3//include/qstring.h&#39;, 2900, 116, 24)
 (&#39;/usr/include/kconfigskeleton.h&#39;, 2280, 30, 75)
 (&#39;/usr/include/klineedit.h&#39;, 1955, 17, 114)
 (&#39;/usr/lib/qt3//include/qobject.h&#39;, 1605, 107, 14)
 (&#39;/usr/include/kapplication.h&#39;, 850, 34, 24)
 (&#39;/usr/lib/gcc/i586-mandrake-linux-gnu/3.4.1/include/stddef.h&#39;, 808, 808, 0)
 (&#39;/usr/lib/qt3//include/qwinexport.h&#39;, 784, 784, 0)
 (&#39;/usr/lib/qt3//include/qptrlist.h&#39;, 560, 112, 4)
 (&#39;/usr/include/sys/types.h&#39;, 546, 42, 12)
 (&#39;/usr/local/include/taglib/taglib.h&#39;, 432, 6, 71)
 (&#39;/usr/lib/qt3//include/qnamespace.h&#39;, 420, 84, 4)
 (&#39;/usr/include/kaction.h&#39;, 396, 22, 17)
 (&#39;/usr/include/kguiitem.h&#39;, 216, 27, 7)
 (&#39;/usr/include/kdirlister.h&#39;, 189, 9, 20)
 (&#39;/usr/lib/gcc/i586-mandrake-linux-gnu/3.4.1/include/limits.h&#39;, 184, 184, 0)
 (&#39;/usr/include/kfiledialog.h&#39;, 182, 7, 25)
 (&#39;/usr/lib/gcc/i586-mandrake-linux-gnu/3.4.1/../../../../include/c++/3.4.1/fstream&#39;, 176, 4, 43)
 (&#39;/usr/include/klistview.h&#39;, 161, 23, 6)
 (&#39;/usr/include/kactioncollection.h&#39;, 156, 13, 11)
 (&#39;/usr/include/kdiroperator.h&#39;, 144, 3, 47)
 (&#39;/usr/include/time.h&#39;, 143, 143, 0)
 (&#39;/usr/include/kpopupmenu.h&#39;, 143, 13, 10)
 (&#39;/usr/include/bits/wordsize.h&#39;, 142, 142, 0)
 (&#39;/usr/lib/qt3//include/qdir.h&#39;, 140, 28, 4)
 (&#39;/usr/lib/qt3//include/private/qucomextra_p.h&#39;, 129, 43, 2)
 (&#39;/usr/lib/qt3//include/qmetaobject.h&#39;, 129, 43, 2)
 (&#39;/usr/lib/gcc/i586-mandrake-linux-gnu/3.4.1/../../../../include/c++/3.4.1/iostream&#39;, 126, 3, 41)
</code></pre><p>This is a larger project than the previous example (764 cpp files), so the potential gains in build time are also much higher. The top 10 headers are all included in many files as well as quite expensive, so they would all be great candidates to add to a pre-compiled header list. Considering that it took about 10 minutes to build on my 3GHz machine, I&rsquo;d say it would definitely benefit from some judicious use of pre-compiled headers.</p>
<h3 id="multiplatform-development">Multiplatform development</h3>
<p>A lot of C++ compilers support pre-compiled headers nowadays (gcc, Visual C++, and Codewarrior for sure). Unfortunately, there are still compilers and platforms out there without pre-compiled header support that we need to deal with.</p>
<p>Usually, the code will build the same in a platform without pre-compiled header support, but it will be much, much slower because not only do we not have the caching effect of pre-compiled headers, but we&rsquo;re also including more headers in every compilation unit as part of the PreCompiled.h file. So if we&rsquo;re not careful, all the build speedups we gained using pre-compiled headers are going to come back and slow down builds in platforms without pre-compiled header support by a huge factor.</p>
<p>The best way to deal with this is to be able to turn on the pre-compiled headers on and off. For example, your pre-compiled header file might look like this:</p>
<pre tabindex="0"><code> #ifdef USE_PRECOMPILED_HEADERS
 #include &lt;string&gt;
 #include &lt;sstream&gt;
 #include &lt;iostream&gt;
 #endif
</code></pre><p>For platforms without pre-compiled header support, just don&rsquo;t define USE_PRECOMPILED_HEADERS. Clearly, for this to work every cpp file needs to include all the header files it needs to, independently of whether they&rsquo;ve been included in PreCompiled.h or not. This is not a bad habit to get in anyway, because it makes dependencies more explicit and it doesn&rsquo;t slow the build down any (because all those header files are already in the pre-compiled headers, so they&rsquo;re free).</p>
<p>Having the ability to turn it on and off also allows us to do builds sometimes without relying on pre-compiled headers. This might be useful if we want to verify that files can compile on their own or if we want to generate lists of includes to feed to the script described earlier to find good candidates for adding to the pre-compiled header list.</p>
<h3 id="maintenance">Maintenance</h3>
<p>Pre-compiled headers are mostly fire and forget. You set them up once with the big offenders and leave them be. However, the more a library changes, the more it might benefit from an update of the pre-compiled headers. Whenever a library feels like it&rsquo;s building slowly, you should see if there are any obvious headers that should be added to the pre-compiled header list.</p>
<p>That&rsquo;s one reason I like to display the build times for each library (in my case, I like to include unit test times as well). It&rsquo;s too easy to let a library build more and more slowly over time without ever realizing it. It&rsquo;s like the proverbial frogs taking a hot bath. But if you have hard data, you can see that the library is now taking 10 seconds to build, but last week it was only taking 6 seconds (yes, it doesn&rsquo;t seem like much, but when you have 50+ libraries it quickly adds up!). For bonus points, I want my automated build system to keep historical data of build times and display a plot over time, which will make zeroing in build slowdowns much easier.</p>
<p>If you&rsquo;re interested in maintaining compatibility with other platforms, I&rsquo;d recommend doing a build with pre-compiled header support turned off every so often (once a night or even once a week), and make sure everything works fine. While you&rsquo;re at it, take a pass at the code with <a href="http://www.gimpel.com/html/pcl.htm">PCLint</a>, and you&rsquo;ll be horrified at how many dangerous things you missed.</p>
<p>There really are almost no excuses not to use pre-compiled headers in a large C++ project. If you&rsquo;re not using them, you&rsquo;re doing yourself a disservice. And if you&rsquo;re already using them, you might be able to tweak them a bit and squeeze an extra 10-20% speedup out of your builds. Whatever you do, make sure to keep those build times low to have as fast an edit-build-run cycle as possible.</p>
<p><a href="/wp-content/uploads/bin/list_precomp_py.txt"><img alt="icon" loading="lazy" src="/the-care-and-feeding-of-pre-compiled-headers/images/script.png"> list_precomp.py</a></p>]]></content:encoded></item><item><title>How Incredible Is Incredibuild?</title><link>https://gamesfromwithin.com/how-incredible-is-incredibuild/</link><pubDate>Sun, 06 Feb 2005 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/how-incredible-is-incredibuild/</guid><description>&lt;p&gt;There is no doubt that &lt;a href="http://www.xoreax.com/"&gt;Xoreax&amp;rsquo;s Incredibuild&lt;/a&gt; will speed up most full builds of C++ projects using Microsoft Visual C++ to varying degrees. I&amp;rsquo;m not going to argue that. But is using Incredibuild in your project really a good idea?&lt;/p&gt;</description><content:encoded><![CDATA[<p>There is no doubt that <a href="http://www.xoreax.com/">Xoreax&rsquo;s Incredibuild</a> will speed up most full builds of C++ projects using Microsoft Visual C++ to varying degrees. I&rsquo;m not going to argue that. But is using Incredibuild in your project really a good idea?</p>
<p>Chances are that if you&rsquo;re reading this, you already know what <a href="http://www.xoreax.com/">Xoreax&rsquo;s Incredibuild</a> is. If not, here&rsquo;s the quick summary: Incredibuild is a distributed build system for Microsoft Visual C++ that recruits other machines in the network to parallelize your build; it claims build time reductions of up to 90%. There is no doubt that Incredibuild will speed up most full builds of C++ projects using Microsoft Visual C++ to varying degrees. I&rsquo;m not going to argue that. But is using Incredibuild in your project really a good idea?</p>
<p>Let&rsquo;s start with the positives. Incredibuild does work as advertised and can produce significant speed ups from distributing your build. It is well polished and it has clearly been tested in real-world application development. It has good load balancing, you won&rsquo;t notice your machine being used as a slave, it has the concept of backup coordinators, it minimizes network usage, etc, etc. It does have a few technical glitches, but I&rsquo;ll get to those later. All in all, it&rsquo;s pretty robust and well-thought-out product, and there are clearly <a href="http://www.xoreax.com/purchase_testimonials.htm">lots of people happy with it</a> (interestingly, the list includes many game developers).</p>
<p>So, what&rsquo;s not to like? When I started using Incredibuild last year, I was initially floored by the results. A project that would take 45 minutes to compile, would only take about 5-8 minutes with Incredibuild. Wow! That&rsquo;s what I call a â€œsignificantâ€ speedup!</p>
<p>However, the more I used it, the more it started getting in the way and the more it made me think about all the areas where it was lacking. Be warned that this doesn&rsquo;t pretend to be a rigorous review with objective data to back up what I&rsquo;m saying. These are the issues I&rsquo;ve encountered using Incredibuild without trying to become an expert at it. It&rsquo;s very likely that are ways around some of the things I&rsquo;m going to complain about. If so, feel free to let me know in the comments below. Maybe I&rsquo;ll change my mind and I&rsquo;ll become an Incredibuild fan after all.</p>
<h3 id="iteration-time">Iteration time</h3>
<p><img alt="tools" loading="lazy" src="/how-incredible-is-incredibuild/images/tools.jpg"> <strong>Slow incremental builds.</strong> I don&rsquo;t mean incremental linking (that comes next), I mean non-full builds, like the case where I change a single line in a cpp file and want to generate a new executable. I found that using Incredibuild for such builds is significantly slower than the regular build in MSVC (incidentally, <a href="http://www.xoreax.com/support_faq.htm#q6">this FAQ</a> claims exactly the opposite). I like to compile my code after every single change. Actually, I like to compile it and run all the tests after every single change. I&rsquo;ll often even do it while I&rsquo;m thinking. It&rsquo;s a (good) habit you get in after you&rsquo;ve been doing test-driven development for a while. Anything that slows down that cycle is a major impediment. So what if I do incremental builds with the regular MSVC build and just use Incredibuild for full rebuilds? Read on&hellip;</p>
<p><strong>Problems mixing and matching object files.</strong> Mixing and matching object files created by Incredibuild and MSVC seems to work&hellip; sometimes. I know in their <a href="http://www.xoreax.com/support_faq.htm">FAQ</a> they indicate a few changes you need to do to the debug information settings to prevent some errors. I&rsquo;m talking about bigger issues. As in, the executable generated is total garbage and crashes right away. Usually doing a full rebuild with Incredibuild fixes it (sit and wait 5-8 minutes). When this is caused just by changing a single cpp file, it gets old very quickly and you start questioning the benefits you&rsquo;re getting in the first place.</p>
<p>I found that I have similar problems matching object files with incremental linking turned on (this time in the form of errors during the build). The only way I&rsquo;ve managed to more or less reliably mix both types of object files is by turning off incremental linking completely. Of course, link times are often the bottleneck of the change-build-test cycle, being as high as a full minute or more when you&rsquo;re dealing with the whole game. Incremental linking, as long as you&rsquo;re only modifying the executable project, is really a god-send and can reduce a 1+ minute link time to just a couple of seconds. Again, turning it off to be able to use Incredibuild seems a step backwards.</p>
<p><strong>No edit and continue.</strong> I admit it, I&rsquo;ve never been a fan of edit and continue. But some people swear by it, and it&rsquo;s yet another feature you can&rsquo;t have turned on with Incredibuild. Interestingly, their FAQ fails to mention the words â€œincremental linkingâ€ or â€œedit and continueâ€ anywhere. (Actually, they had it under <a href="http://www.xoreax.com/support_knownissues.htm#ki02">&ldquo;known issues&rdquo;</a>).</p>
<h3 id="technical-issues">Technical issues</h3>
<p><strong>Tied to Microsoft Visual Studio.</strong> Are you developing for other platforms than Windows or Xbox? Are you using other compilers than Visual C++? Then you&rsquo;re out of luck. You&rsquo;ll have to come up with a totally different system to build your code for those platforms. You can&rsquo;t use the same build back end because Incredibuild is totally tied to MSVC. I don&rsquo;t know exactly why, I just hope they had a very good technical reason and it wasn&rsquo;t to get prettier integration with colorful progress graphics. At least it is possible to run Incredibuild from the command line (still using MSVC of course), which is essential for build machines. <strong>Update:</strong> msew just pointed out that <a href="http://www.xoreax.com/company_news022.htm">version 2.20 has beta support for the Inteal compiler</a>. Good to hear that.</p>
<p><strong>Uses Microsoft Visual Studio&rsquo;s build system.</strong> If I could rip one thing from Visual Studio, it would be the completely broken build system. I don&rsquo; t know what they were thinking when they built it, and I have a very hard time believing anybody at Microsoft uses it for complex projects. It seems a great quick way to get toy projects off the ground, but it doesn&rsquo;t scale well at all to large projects (very much like those GUI wizards, but people seem to put up with them anyway). In a real build system I want to have multiple targets (and combinations of those targets), I want to be able to enforce build order, I want to be able to choose <strong>not</strong> to link a project just because I make it dependent on another project, I want to be able to have over a hundred different projects in an environment and not bog down because of it, I want to be able to view and change build settings easily across projects. In other words, I want primarily something like make, Jam, or Scons. Fortunately, MSVC allows you to have makefile projects, but Incredibuild <a href="http://www.xoreax.com/support_faq.htm#q33">doesn&rsquo;t support them</a>. This is particularly important to me because I would like to use a common back end for all the different platforms, and I&rsquo;d love to have a single build file that I can use to build any project or platform combination.</p>
<p><strong>Failing to build correctly.</strong> Every so often, a build with Incredibuild will completely fail because some dependency check failed along the way (this seems to happen particularly when changing header files outside of the project itself, like middleware or other external APIs). To be fair, this seems to happen just as frequently in MSVC with regular builds using pre-compiled headers, so you probably can&rsquo;t blame Incredibuild for it. It certainly doesn&rsquo;t fix the problem though.</p>
<p><strong>Builds are done differently than local ones.</strong> I haven&rsquo;t investigated this one thoroughly, but Incredibuild uses slightly different rules than regular, local builds. As a result, it is possible to set up a build with custom rules that builds correctly in Incredibuild, but fails as a regular build. If you&rsquo;re trying to mix and match the two, that can&rsquo;t be good news. I think the source of the problem is that Incredibuild runs custom build rules locally as the first step of the build, and then distributes the rest. Regular local builds will call the custom build rule when they get to the file in question, so you can see how there&rsquo;s a slight potential for problems there (this, incidentally, is not idle nit picking, but happened in a real project).</p>
<h3 id="performance">Performance</h3>
<p><strong>Network issues can affect performance significantly.</strong> For a while, Incredibuild kept having all sorts of problems communicating across the network and was causing builds to either take forever or never complete (some slave machine would just never return a result or timeout). I don&rsquo;t know if that was caused by glitches in our network, too many people using it, or bugs in Incredibuild, but it was highly annoying. I suppose you&rsquo;re bound to have that happen in any distributed system, but I would expect them to always be able to fall back to local compilation and not take any longer than a non-distributed build.</p>
<p><strong>How much faster than a regular full build?</strong> This is the big question. I have seen with my own eyes that using Incredibuild on a project without physical insulation and carefully managed dependencies, and without precompiled headers, can make the build be many, many times faster. But how does it compare to a project that has been carefully managed, with well-thought-out precompiled headers? As an experiment, I retrofitted a large codebase to use precompiled headers. The awful physical dependencies were still there, and I&rsquo;m sure the precompiled headers were less than ideal. Still, build times went down from 45 minutes to something like 10 minutes. Incredibuild took 5-8 minutes in that same codebase. Throw a faster machine with multiple cores (the future of PCs), and a decent build system that can use multiple threads (not MSVC, go figure), and I think you can get similar build times without any of the drawbacks.</p>
<h3 id="architectural-issues">Architectural issues</h3>
<p>Here is one argument that cuts both ways.</p>
<p>Programmers will often try to avoid making changes that cause full rebuilds (to avoid spending 30+ minutes waiting for a result), but they end up doing it by hacking things in the wrong place: duplicating code, declaring externs by hand on the wrong file, etc. Ideally, you shouldn&rsquo;t have many files that can cause a full rebuild (if you do, you have a big problem), but if you need to make a change there, you really should do it. Incredibuild can ease the pain of a full rebuild and prevent the hack, leading to a cleaner codebase and architecture.</p>
<p>On the other hand, having Incredibuild around can cause developers to throw caution to the wind and think they don&rsquo;t have to worry about physical dependencies anymore. As a result, they end up with <a href="http://www.antipatterns.com/briefing/sld024.htm">the blob antipattern</a>. Ironically, after a few months of that, they&rsquo;ll probably end up with really slow build times again (because almost every file causes a full rebuild).</p>
<p>Is the time spent in managing and minimizing <a href="/physical-structure-and-c-part-1-a-first-look/%20">physical dependencies</a> worth it? Absolutely! Low physical dependencies also means low logical dependencies. Even if build times were instant, you would still be well advised to pay very close attention to dependencies and minimize them (not just for reuse or maintenance, but even during the development of the game, since it makes it much easier to refactor or change any part of your program).</p>
<h3 id="alternatives">Alternatives</h3>
<p>What are the alternatives to Incredibuild then? Are we stuck with really slow builds?</p>
<ul>
<li>Manage your physical dependencies. Be as careful as you can about them, and you&rsquo;ll be way on your way towards minimizing build times. Use the <a href="http://c2.com/cgi/wiki?PimplIdiom">pimpl idiom</a> in any header that is used extensively throughout the codebase.</li>
<li>Use precompiled headers. Stay away from that option of â€œautomatic precompiled headersâ€ in MSVC because it does more harm than good. Use <a href="http://www.cygnus-software.com/papers/precompiledheaders.html">Bruce Dawson&rsquo;s paper</a> as a starting point about precompiled headers. Also, precompiled headers are supported across the board for most popular C++ compilers: MSVC, gcc, Codewarrior, etc, so you can get a lot of benefits from a single approach.</li>
<li>Get a <strong>fast</strong> dual-core machine and use multiple threads to build. You can&rsquo;t do that with MSVC, but man, Jam and Scons can certainly do it. I stress the fast CPU part. In the past, I ran some tests, and, assuming you have enough memory, compilation time was not limited by disk space but by CPU speed. Once you start using multiple threads it&rsquo;ll put more stress on the disk so it&rsquo;ll probably be a good idea to get fast hard drives as well.</li>
<li><a href="http://distcc.samba.org/">distcc</a>. I admit I&rsquo;ve only tested distcc in toy sample projects, but it&rsquo;s exactly what I would like on paper: a fairly generic distributed build system. It comes with gcc support out of the â€œbox,â€ but it can be extended to support other compilers. It uses a very clean way of distributing the builds, by running the preprocessor locally and sending the output file to be compiled into an object file. I really don&rsquo;t know how it scales for a real-world project, but I&rsquo;d like to learn more about it.</li>
<li><a href="http://www.scons.org/">Scons</a>&rsquo; network cache. Scons can transparently cache object files on the network, so if you ever try to build a file that is already in the cache, you&rsquo;ll get it instantly. This can be a reasonable solution to avoiding full rebuilds after one person (or the build machine) has done it once.</li>
</ul>
<h3 id="conclusion">Conclusion</h3>
<p>If you&rsquo;re stuck with some legacy code that takes forever to compile, don&rsquo;t hesitate to get Incredibuild. It&rsquo;ll do wonders for your project and will cut down your build times by a huge amount. If you&rsquo;re developing on a new code base, or your build times are short already, I would recommend against using it. For the project I&rsquo;m starting now, we&rsquo;re starting without Incredibuild (even though we already have the licenses, so it&rsquo;s not a money issue) and we&rsquo;re carefully managing physical dependencies and using precompiled headers. If at some point it grows very large and we see benefits from Incredibuild, we might switch, but until then, we&rsquo;re a lot better off without it.</p>]]></content:encoded></item><item><title>Even More Experiments with Includes</title><link>https://gamesfromwithin.com/even-more-experiments-with-includes/</link><pubDate>Wed, 26 Jan 2005 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/even-more-experiments-with-includes/</guid><description>&lt;p&gt;One aspect of the scientific process is publishing detailed experiment descriptions and results so that they can be independently verified by other scientists. That&amp;rsquo;s exactly what I decided to do after reading Kyle Wilson&amp;rsquo;s surprising results in his article &amp;ldquo;&lt;a href="http://gamearchitect.net/Articles/ExperimentsWithIncludes.html"&gt;Experiments with Includes&lt;/a&gt;.&amp;rdquo;&lt;/p&gt;</description><content:encoded><![CDATA[<p>One aspect of the scientific process is publishing detailed experiment descriptions and results so that they can be independently verified by other scientists. That&rsquo;s exactly what I decided to do after reading Kyle Wilson&rsquo;s surprising results in his article &ldquo;<a href="http://gamearchitect.net/Articles/ExperimentsWithIncludes.html">Experiments with Includes</a>.&rdquo;</p>
<p>Kyle found that using <a href="http://c2.com/cgi/wiki?RedundantIncludeGuards">internal include guards</a> was significantly slower than using #pragma once with the C++ compiler in Microsoft Visual Studio 2003 and 2005 beta. That just flies in the face of the <a href="/physical-structure-and-c-part-1-a-first-look/%20">measurements I had done before</a> and what <a href="http://sourceforge.net/mailarchive/message.php?msg_id=2704308">other people had reported</a>. How was it possible?</p>
<p>The first thing that struck me when looking at Kyle&rsquo;s results is that he&rsquo;s using an extremely pathological case: 200 header files, each of them including all 200 headers. Still, the point is to measure header include performance, so maybe that was fine. More on that later.</p>
<p>The first thing I did was to write a <a href="/wp-content/uploads/bin/generate_includes.py">quick script</a> to generate a set of header files and main file given some parameters. I took the chance to write in Python, which displaced Perl as my favorite scripting language a few months ago. The script will generate a certain number of header files, using either no guards, internal guards, external guards, or pragma statements. In order to be able to compile no guards (and to keep things a bit more realistic), I actually had each header file include all the header files with numbers higher than itself. Feel free to download the script and play with it if you want to run the measurements yourself.</p>
<p><img alt="jungle" loading="lazy" src="/even-more-experiments-with-includes/images/stopWatch.jpg"> Since I&rsquo;m running Linux at home, I first ran the experiment with gcc 3.4.1. First I tested no guards, but I had to keep it to a set of 20 header files to avoid taking forever with an astronomical number of includes (they really add up combinatorially!). As expected, even a 20x20 half-matrix of includes too a while to compile: 2+ minutes. The same set of headers with internal include guards was just a blip at 0.15s. So far, so good. That&rsquo;s what I expected.</p>
<p>Now I cranked things up to 200 headers like Kyle had done. Here comes the first surprise of the day: gcc blows up trying to parse that many includes. I get a â€œ#include nested too deeplyâ€ error. Digging through the <a href="http://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Invoking-GCC.html#Invoking%20GCC">gcc documentation</a> I wasn&rsquo;t able to find any way to increase that depth. That made me realize that having include chains of 200+ headers is completely unrealistic. I knew that it was artificially large, but it&rsquo;s probably so by an order of magnitude at least.</p>
<p>Still, just for the test, I decided to go ahead. It turns out it was choking very near the end, so doing a run with 195 headers worked just fine. The results were what I would have expected. A bit better actually, and certainly much better than the results Kyle saw in Visual Studio: all the runs (internal guards, external guards, and pragma) took about the same time (0.07 seconds), and each of them included exactly 195 headers. No more, no less. That&rsquo;s exactly how I would expect the compiler to behave.</p>
<p>gcc 3.4.1 (Linux with 2.6 kernel). 195 headers.</p>
<ul>
<li>Internal guards: 0.07s</li>
<li>External guards: 0.09s</li>
<li>Pragma directive: 0.07s</li>
</ul>
<p>At work, I&rsquo;m not as lucky, and I have to use Windows and Microsoft Visual Studio, so I ran the second set of tests there. The results confirmed what Kyle reported: The internal guards were very slow (14+ seconds), the external guards where blazingly fast (0.37 seconds), and the pragma directive was somewhere in between (9.6 seconds).</p>
<p>Microsoft Visual Studio 2003. 195 headers.</p>
<ul>
<li>Internal guards: 14.7s</li>
<li>External guards: 0.37s</li>
<li>Pragma directive: 9.57s</li>
</ul>
<p>I was pretty amazed to see that. It seems like a major flaw in the Visual C++ compiler, doesn&rsquo;t it?</p>
<p>To round out the tests, since I had the Metrowerks PS2 compiler handy, I decided to run the same set of tests with it. It turns out that it completely blew up, complaining of includes nested too deeply with the project with 195 headers. To my surprise, I had to lower the number of includes to 30 in order to be able to compile it at all. Anything over 30 would cause it to blow up.</p>
<p>That made me think again about the worst cases I would see in a typical project, and I realized that having over 30 includes deep at once is probably very, very rare, even if you&rsquo;re using STL or Boost, which make heavy use of header files.</p>
<p>Just for the sake of completeness, I decided to run the tests with just 30 includes and see if I could discern any patterns from the results. It turns out that Metrowerks is pretty slow overall, but at least the differences between the three approaches are minimal.</p>
<p>Metrowerks PS2 compiler v3.0. 30 headers.</p>
<ul>
<li>Internal guards: 0.60s</li>
<li>External guards: 0.46s</li>
<li>Pragma directive: 0.49s</li>
</ul>
<p>I ran the same set of tests with Visual Studio and it showed the external includes being the clear winner, but internal and pragmas being almost the same. I wonder if Visual C++ uses some dynamic algorithm that avoids having a fixed hard limit on include depth at the cost of runtime performance. I&rsquo;ll take a fixed depth and flawless behavior like gcc any day personally.</p>
<p>Microsoft Visual Studio 2003. 30 headers.</p>
<ul>
<li>Internal guards: 0.48s</li>
<li>External guards: 0.14s</li>
<li>Pragma directive: 0.41s</li>
</ul>
<p>gcc was so fast with such a tiny project that I couldn&rsquo;t reliably measure it. But if the 195 includes was taking 0.07 seconds, you can guess how fast it churned through just 30 header files.</p>
<h3 id="conclusion">Conclusion</h3>
<p>It does seem that Microsoft Visual Studio has some major problems with includes in pathological situations. On the other hand, it also seems that those situations are completely unrealistic and will never happen in a real code base. For a more realistic situation (30x30 half matrix), internal guards and pragmas are the same, and external guards have somewhat of an edge.</p>
<p>gcc behaved like a real champion by being super fast and efficient no matter what technique you threw at it. Way to go! The Microsoft compiler certainly could stand some improvement in that area.</p>
<p>Metrowerks was the slowest of the bunch, but it dealt with all the different techniques just fine for a relatively small set of tests.</p>
<p>Overall, there should be no real difference between using internal guards and pragma directives (which happily confirms some of the measurements we had done in real code bases). So stick with internal guards, which are standard and work on any compiler, but if adding a #pragma once directive surrounded by conditionals (because it&rsquo;s not standard and it&rsquo;s not supported in all the compilers) in addition to the internal guards would make you sleep better, go for it. External guards might have an edge with Visual Studio, but the pain and potential trouble of using external guards clearly outweighs any speed benefits gained by using them.</p>
<p><a href="/wp-content/uploads/bin/generate_includes.txt"><img alt="icon" loading="lazy" src="/even-more-experiments-with-includes/images/script.png"> generate_includes.py</a></p>]]></content:encoded></item><item><title>Exploring the C++ Unit Testing Framework Jungle</title><link>https://gamesfromwithin.com/exploring-the-c-unit-testing-framework-jungle/</link><pubDate>Wed, 29 Dec 2004 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/exploring-the-c-unit-testing-framework-jungle/</guid><description>&lt;p&gt;&lt;strong&gt;Update (Apr 2010):&lt;/strong&gt; It&amp;rsquo;s been quite a few years since I originally did this comparison. Since then, &lt;a href="http://cnicholson.net/"&gt;Charles Nicholson&lt;/a&gt; and I created &lt;a href="http://unittest-cpp.sourceforge.net/"&gt;Unit Test++&lt;/a&gt;, a C/C++ unit-testing framework that addresses most of my requirements and wish-list items. It&amp;rsquo;s designed to be a light-weight, high-performance testing framework, particularly aimed at games and odd platforms with limited functionality. It&amp;rsquo;s definitely my framework of choice and I haven&amp;rsquo;t looked at new ones in several years because it fits my needs so well. I definitely encourage you to check it out.&lt;/p&gt;
&lt;p&gt;-&amp;mdash;&amp;mdash;&amp;mdash;&lt;/p&gt;
&lt;p&gt;One of the topics I&amp;rsquo;ve been meaning to get to for quite a while is the applicability of test-driven development in games. Every time the topic comes up in conversations or mailing lists, everybody is always very curious about it and they immediately want to know more. I will get to that soon. I promise!&lt;/p&gt;
&lt;p&gt;In the meanwhile I&amp;rsquo;m now in the situation that I need to choose a unit-testing framework to roll out for my team at work. So, before I get to talk about how to use &lt;a href="http://www.testdriven.com/modules/news/"&gt;test-driven development&lt;/a&gt; in games, or the value of unit testing, or anything like that, we dive deep into a detailed comparison of existing C++ unit-testing frameworks. Hang on tight. It&amp;rsquo;s going to be a long and bumpy ride with a plot twist at the end.&lt;/p&gt;</description><content:encoded><![CDATA[<p><strong>Update (Apr 2010):</strong> It&rsquo;s been quite a few years since I originally did this comparison. Since then, <a href="http://cnicholson.net/">Charles Nicholson</a> and I created <a href="http://unittest-cpp.sourceforge.net/">Unit Test++</a>, a C/C++ unit-testing framework that addresses most of my requirements and wish-list items. It&rsquo;s designed to be a light-weight, high-performance testing framework, particularly aimed at games and odd platforms with limited functionality. It&rsquo;s definitely my framework of choice and I haven&rsquo;t looked at new ones in several years because it fits my needs so well. I definitely encourage you to check it out.</p>
<p>-&mdash;&mdash;&mdash;</p>
<p>One of the topics I&rsquo;ve been meaning to get to for quite a while is the applicability of test-driven development in games. Every time the topic comes up in conversations or mailing lists, everybody is always very curious about it and they immediately want to know more. I will get to that soon. I promise!</p>
<p>In the meanwhile I&rsquo;m now in the situation that I need to choose a unit-testing framework to roll out for my team at work. So, before I get to talk about how to use <a href="http://www.testdriven.com/modules/news/">test-driven development</a> in games, or the value of unit testing, or anything like that, we dive deep into a detailed comparison of existing C++ unit-testing frameworks. Hang on tight. It&rsquo;s going to be a long and bumpy ride with a plot twist at the end.</p>
<p>If you just want to read about a specific framework, you can go directly there:</p>
<ul>
<li><a href="#cppunit">CppUnit</a></li>
<li><a href="#boost">Boost.Test</a></li>
<li><a href="#cppunitlite">CppUnitLite</a></li>
<li><a href="#nanocppunit">NanoCppUnit</a></li>
<li><a href="#unitpp">Unit++</a></li>
<li><a href="#cxxtest">CxxTest</a></li>
</ul>
<p><strong>Overview</strong></p>
<p><img alt="jungle" loading="lazy" src="/exploring-the-c-unit-testing-framework-jungle/images/jungle_tikal.jpg"> How do we choose a <a href="http://c2.com/cgi/wiki?TestingFramework">unit-testing framework</a>? It depends on what we&rsquo;re going to do with it and how we&rsquo;re going to use it. If I used Java for most of my work, the choice would be easy since <a href="http://www.junit.org/index.htm">JUnit</a> seems to be the framework of choice for those working with Java. I don&rsquo;t hear them arguing over frameworks or proposing new ones very frequently, so it must be pretty good.</p>
<p>Unfortunately that&rsquo;s not the case with C++. We have our XUnit family member, CppUnit, but we&rsquo;re clearly not happy with that. We have more unit-testing frameworks than you can shake a stick at. And a lot of teams end up writing their own from scratch. Why is that? Is C++ so inadequate for unit testing that we have trouble fitting the XUnit approach in the language? Not like it&rsquo;s a bad thing, mind you. Diversity is good. Otherwise I would be stuck writing this under Windows and you would be stuck reading it with Internet Explorer. In any case, I&rsquo;m clearly not the first one who&rsquo;s asked this question. <a href="http://c2.com/cgi/wiki?WhySoManyCplusplusTestFrameworks">This page</a> tries to answer the question, and comes up with some very plausible answers: differences in compilers, platforms, and programming styles. C++ is not exactly a clean, fully supported language, with one coding standard.</p>
<p>A good way to start is to create a list of features that are important given the type of work I expect to be doing. In particular, I want to be doing test-driven development (TDD), which means I&rsquo;m going to be constantly writing and running many small tests. It&rsquo;s going to be used for game development, so I&rsquo;d like to run the tests in a variety of different platforms (PC, Xbox, PS2, next-generation consoles, etc). It should also fit my own personal TDD style (many tests, heavy use of fixtures, etc).</p>
<p>The following list summarizes the features I would like in a unit-testing framework in order of importance. I&rsquo;ll evaluate each framework on the basis of these features. Thanks to <a href="http://fancy.org/">Tom Plunket</a> for providing a slightly different view on the topic that helped me to re-evaluate the relative importance of the different features.</p>
<ol>
<li><strong>Minimal amount of work needed to add new tests</strong>. I&rsquo;m going to be doing this all the time, so I don&rsquo;t want to do a lot of typing, and I especially don&rsquo;t want to do any duplicated typing. The shorter and easier it is to write, the easier it&rsquo;ll be to refactor, which is crucial when you&rsquo;re doing TDD.</li>
<li><strong>Easy to modify and port.</strong> It should have no dependencies with non-standard libraries, and it shouldn&rsquo;t rely on â€œexoticâ€ C++ features if possible (RTTI, exception handling, etc). Some of the compilers we have to use for console development are not exactly cutting edge. To verify this one, I created a set of unit tests using each library under Linux with g++. Since most of the tests are written with Windows and Visual Studio in mind, it&rsquo;s not a bad initial test.</li>
<li><strong>Supports setup/teardown steps (<a href="http://c2.com/cgi/wiki?TestFixture">fixtures</a>).</strong> I&rsquo;ve adopted the style recommended by David Astels in his book <a href="http://www.amazon.com/exec/obidos/ASIN/0131016490/ref=nosim/gamesfromwith-20">Test Driven Development: A Practical Guide</a> about using only one assertion per test. It really makes tests a lot easier to understand and maintain, but it requires heavy use of fixtures. A framework without them is ruled out immediately. Bonus points for frameworks that let me declare objects used in the fixture on the stack (and still get created right before the test) as opposed to having to allocate them dynamically.</li>
<li><strong>Handles exceptions and crashes well.</strong> We don&rsquo;t want the tests to stop just because some code that was executed accessed some invalid memory location or had a division by zero. The unit-testing framework should report the exception and as much information about it as possible. It should also be possible to run it again and have the debugger break at the place where the exception was triggered.</li>
<li><strong>Good assert functionality.</strong> Failing assert statements should print the content of the variables that were compared. It should also provide a good set of assert statements for doing â€œalmost equalityâ€ (absolutely necessary for floats), less than, more than, etc. Bonus points for providing ways to check whether exceptions were or were not thrown.</li>
<li><strong>Supports different outputs.</strong> By default, I&rsquo;d like to have a format that can be understood and parsed by IDEs like Visual Studio or <a href="http://www.kdevelop.org/">KDevelop</a>, so it&rsquo;s easy to navigate to any test failures as if they were syntax errors. But I&rsquo;d also like to have ways to display different outputs (more detailed ones, shorter ones, parsing-friendly ones, etc).</li>
<li><strong>Supports <a href="http://c2.com/cgi/wiki?TestSuite">suites</a>.</strong> It&rsquo;s kind of funny that this is so low in my priority list when it&rsquo;s usually listed as a prominent feature in most frameworks. Frankly, I&rsquo;ve had very little need for this in the past. It&rsquo;s nice, yes, but I end up having many libraries, each of them with its own set of tests, so I hardly ever need this. Still, it certainly would be nice to have around in case it starts getting slow to run the unit tests at some point.</li>
</ol>
<p>Bonus: Timing support. Both for total running time of tests, and for individual ones. I like to keep an eye on my running times. Not for performance reasons, but to prevent them from getting out of hand. I prefer to keep running time to under 3-4 seconds (it&rsquo;s the only way to be able to run them very frequently). Ideally, I&rsquo;d also like to see a warning printed if any single test goes over a certain amount of time.</p>
<p>Easy of installation was not considered a priority; after all, I only have to go through that onceâ€”it&rsquo;s creating new tests that I&rsquo;m going to be doing all day long. Non-commercial-friendly licenses (like GPL or LGPL) are also not much of an issue because the unit test framework is not something we&rsquo;re going to link to the executable we ship, so they don&rsquo;t really impose any restrictions on the final product.</p>
<p>Incidentally, during my research for this article, I found that other people have compiled <a href="http://c2.com/cgi/wiki?ConsiderationsForAndComparisonOfCplusplusTestFrameworks">lists of what they wish for in C++ unit-testing frameworks</a>. It&rsquo;s interesting to contrast that article with this one and make a note of the differences and similarities between what we&rsquo;d like to see in a unit test framework.</p>
<p><strong>Ideal Framework</strong></p>
<p>Before I start going over each of the major (and a few minor) C++ unit-testing frameworks, I decided I would apply the philosophy behind test-driven development to this analysis and start by thinking what I would like to have. So I decided to write the set of sample tests in some ideal unit-testing framework without regard for language constrains or anything. In the ideal world, this is what I would like my unit tests to be like.</p>
<p>The simplest possible test should be trivial to create. Just one line to declare the test and then the test body itself:</p>
<pre tabindex="0"><code>TEST (SimplestTest)
{
  Â  float someNum = 2.00001f;
   Â ASSERT_CLOSE (someNum, 2.0f);
}
</code></pre><p>A test with fixtures is going to be a bit more complicated, but it should still be really easy to set up:</p>
<pre tabindex="0"><code>SETUP (FixtureTestSuite)
{
    float someNum = 2.0f;
    std::string str = &#34;Hello&#34;;
    MyClass someObject(&#34;somename&#34;);
    someObject.doSomethng();
}

TEARDOWN (FixtureTestSuite)
{
    someObject.doSomethingElse();
}

TEST (FixtureTestSuite, Test1)
{
    ASSERT_CLOSE (someNum, 2.0f); someNum = 0.0f;
}

TEST (FixtureTestSuite, Test2)
{
    ASSERT_CLOSE (someNum, 2.0f);
}

TEST (FixtureTestSuite, Test3)
{
    ASSERT_EQUAL(str, &#34;Hello&#34;);
}
</code></pre><p>The first thing to point out about this set of tests is that there is a minimum amount of code spent in anything other than the tests themselves. The simplest possible test takes a couple of lines and needs no support other than a main file that runs all the tests. Setting up a fixture with setup/teardown calls should also be totally trivial. I don&rsquo;t want to inherit from any classes, override any functions, or anything. Just write the setup step and move on.</p>
<p>Look at the setup function again. The variables that are going to be used in the tests are not dynamically created. Instead, they appear to be declared on the stack and used directly there. Additionally, I should point out that those objects should only be created right before each test, and not before all tests start. How exactly are the tests going to use them? I don&rsquo;t know, but that&rsquo;s what I would like to use. That&rsquo;s why this is an ideal framework.</p>
<p>Now let&rsquo;s contrast it to six real unit-testing frameworks that have to worry about actually compiling and running. For each of the frameworks I look at the list of wanted features and I try to implement the two tests I implemented with this ideal framework. <a href="/wp-content/uploads/bin/unit_test_frameworks.tar.gz">Here is the source code for all the examples</a>.</p>
<p>CppUnit is probably the most widely used unit-testing framework in C++, so it&rsquo;s going to be a good reference to compare other unit tests against. I had used CppUnit three or four of years ago and my impressions back then were less than favorable. I remember the code being a mess laced with MFC, the examples all tangled up with the framework, and the silly GUI bar tightly coupled with the software. I even ended up creating a patch to provide console-only output and removed MFC dependencies. So this time I approached it with a bit of apprehension to say the least.</p>
<p>I have to admit that CppUnit has come a long way since then. I was expecting the worst, but this time I found it much easier to use and configure. It&rsquo;s still not perfect, but it&rsquo;s much, much better than it used to. The documentation is pretty decent, but you&rsquo;ll have to end up digging deep into the module descriptions to even find out that some functionality is available.</p>
<ol>
<li><strong>Minimal amount of work needed to add new tests</strong>. This is one of the major downfalls of CppUnit, and, ironically, it&rsquo;s the highest-rated feature I was looking for. CppUnit requires quite a bit of work for the simplest possible test.</li>
</ol>
<pre tabindex="0"><code>// Simplest possible test with CppUnit
#include &lt;cppunit/extensions/HelperMacros.h&gt;
class SimplestCase : public CPPUNIT_NS::TestFixture
{
    CPPUNIT_TEST_SUITE( SimplestCase );
    CPPUNIT_TEST( MyTest );
    CPPUNIT_TEST_SUITE_END();
protected:
    void MyTest();
};

CPPUNIT_TEST_SUITE_REGISTRATION( SimplestCase );  

void SimplestCase::MyTest()
{
    float fnum = 2.00001f;
    CPPUNIT_ASSERT_DOUBLES_EQUAL( fnum, 2.0f, 0.0005 );
}
</code></pre><ol start="3">
<li><strong>Easy to modify and port.</strong> It gets mixed marks on this one. On one hand, it runs under Windows and Linux, and the functionality is reasonably well modularized (results, runners, outputs, etc). On the other hand, CppUnit still requires RTTI, the STL, and (I think) exception handling. It&rsquo;s not the end of the world to require that, but it could be problematic if you want to link against libraries that have no RTTI enabled, or if you don&rsquo;t want to pull in the STL.</li>
<li><strong>Supports fixtures.</strong> Yes. If you want the objects to be created before each test, they need to be dynamically allocated in the setup() function though, so no bonus there.</li>
</ol>
<pre tabindex="0"><code>#include &lt;cppunit/extensions/HelperMacros.h&gt;
#include &#34;MyTestClass.h&#34;
class FixtureTest : public CPPUNIT_NS::TestFixture
{
    CPPUNIT_TEST_SUITE( FixtureTest );
    CPPUNIT_TEST( Test1 );
    CPPUNIT_TEST( Test2 );
    CPPUNIT_TEST( Test3 );
    CPPUNIT_TEST_SUITE_END();
protected:
    float someValue;
    std::string str;
    MyTestClass myObject;
public:
    void setUp();
protected:
    void Test1();
    void Test2();
    void Test3();
};

CPPUNIT_TEST_SUITE_REGISTRATION( FixtureTest );  

void FixtureTest::setUp()
{
    someValue = 2.0;
    str = &#34;Hello&#34;;
}  

void FixtureTest::Test1()
{
    CPPUNIT_ASSERT_DOUBLES_EQUAL( someValue, 2.0f, 0.005f );
    someValue = 0;
    //System exceptions cause CppUnit to stop dead on its tracks
    //myObject.UseBadPointer();
    // A regular exception works nicely though myObject.ThrowException();
}

void FixtureTest::Test2()
{
    CPPUNIT_ASSERT_DOUBLES_EQUAL( someValue, 2.0f, 0.005f );
    CPPUNIT_ASSERT_EQUAL (str, std::string(&#34;Hello&#34;));
}

void FixtureTest::Test3()
{
    // This also causes it to stop completely
    //myObject.DivideByZero();
    // Unfortunately, it looks like the framework creates 3 instances of MyTestClass
    // right at the beginning instead of doing it on demand for each test. We would
    // have to do it dynamically in the setup/teardown steps ourselves.
    CPPUNIT_ASSERT_EQUAL (1, myObject.s_currentInstances);
    CPPUNIT_ASSERT_EQUAL (3, myObject.s_instancesCreated);
    CPPUNIT_ASSERT_EQUAL (1, myObject.s_maxSimultaneousInstances);
}
</code></pre><ol start="6">
<li><strong>Handles exceptions and crashes well.</strong> Yes. It uses the concept of â€œprotectorsâ€ which are wrappers around tests. The default one attempts to catch all exceptions (and identify some of them). You can write your own custom protectors and push them on the stack to combine them with the ones already there. It didn&rsquo;t catch system exceptions under Linux, but it would have been trivial to add with a new protector. I don&rsquo;t think it had a way to easily turn off exception handling and let the debugger break where the exception happened though (no define or command-line parameter).</li>
<li><strong>Good assert functionality.</strong> Pretty decent. It has the minimum set of of assert statements, including one for comparing floating-point numbers. It&rsquo;s missing asserts for less than, greater than, etc. The contents of the variables compared are printed to a stream if the assert fails, giving you as much information as possible about the failed test.</li>
<li><strong>Supports different outputs.</strong> Yes. Has very-well defined functionality for â€œoutputtersâ€ (which display the results of the tests), as well as â€œlistenersâ€ (which get notified while the tests are happening). It comes with an IDE-friendly output that is perfect for integrating with Visual Studio. Also supports GUI progress bars and the like.</li>
<li><strong>Supports suites.</strong> Yes.</li>
</ol>
<p>Overall, CppUnit is frustrating because it&rsquo;s almost exactly what I want, except for my most wanted feature. I really can&rsquo;t believe that it takes so much typing (and duplicated typing at that) to add new tests. Other than that, the main complaint is the need for RTTI or exceptions, and the relative complexity of the source code, which could make it challenging to port to different platforms.</p>
<p><strong>Update:</strong> <em>I&rsquo;ve revised my comments and ratings of the Boost.Test framework in light of the comments from Gennadiy Rozental pointing out how easy it is to add fixtures in boost.</em></p>
<p>I&rsquo;m a big fan of Boost, but I have to admit that it wasn&rsquo;t until about a year ago that I even learned that Boost was providing a unit testing library. Clearly, I had to check it out.</p>
<p>The first surprise is that Boost.Test isn&rsquo;t exclusively a unit-testing framework. It also pretends to be a bunch of other things related to testing. Nothing terribly wrong with that, but to me is the first sign of a â€œsmell.â€ The other surprise is that it wasn&rsquo;t really based on the XUnit family. Hmmm&hellip; In that case, it had better provide some outstanding functionality.</p>
<p>The documentation was top notch. Some of the best I saw for any testing framework. The concepts were clearly explained, and had lots of simple examples to demonstrate different features. Interestingly, from the docs I saw that Boost.Test was designed to support some things that I would consider bad practices such as dependencies between tests, or long tests.</p>
<ol>
<li><strong>Minimal amount of work needed to add new tests</strong>. Almost. Boost.Test requires really minimal work to add new tests. It&rsquo;s very much like the ideal testing framework described earlier. Unfortunately, adding tests that are part of a suite requires more typing and explicit registration of each test.</li>
</ol>
<pre tabindex="0"><code>#include &lt;boost/test/auto_unit_test.hpp&gt;
#include &lt;boost/test/floating_point_comparison.hpp&gt;  

BOOST_AUTO_UNIT_TEST (MyFirstTest)
{
    float fnum = 2.00001f;
    BOOST_CHECK_CLOSE(fnum, 2.f, 1e-3);
}
</code></pre><ol start="3">
<li><strong>Easy to modify and port.</strong> It gets mixed marks on this one, for the same reasons as CppUnit. Being part of the Boost libraries, portability is something that they take very seriously. It worked flawlessly under Linux (better than most frameworks). But I question how easy it is to actually get inside the source code and start making modifications. It also happens to pull into quite a few supporting headers from other Boost libraries, so it&rsquo;s not exactly small and self-contained.</li>
<li><strong>Supports fixtures.</strong> Boost.Test eschews the setup/teardown structure of NUnit tests in favor of plain C++ constructors/destructors. At first this threw me off for a loop. After years of being used to setup/teardown, and a fairly complex suite setup, I didn&rsquo;t see the obvious ways of using fixtures with composition.Now that I&rsquo;ve tried it this way I&rsquo;ve come to like it almost better than setup/teardown fixtures. One of the great advantages of this approach is that you don&rsquo;t need to create fixture objects dynamically, and instead you can put the whole fixture on the stack.On the downside, it&rsquo;s annoying to have to refer to the variables in the fixture through the object name. It would be great if they could somehow magically appear in the same scope as the test case itself. Also, it would have been a bit cleaner if the fixture could have been setup on the stack by the BOOST_AUTO_UNIT_TEST macro instead of having to explicitely put it on the stack for every test case.</li>
</ol>
<pre tabindex="0"><code>#include &lt;boost/test/auto_unit_test.hpp&gt;
#include &lt;boost/test/floating_point_comparison.hpp&gt;
#include &#34;MyTestClass.h&#34;  

struct MyFixture
{
    MyFixture()
    {
        someValue = 2.0;
        str = &#34;Hello&#34;;
    }
    float someValue;
    std::string str;
    MyTestClass myObject;
};

BOOST_AUTO_UNIT_TEST (TestCase1)
{
    MyFixture f;
    BOOST_CHECK_CLOSE (f.someValue, 2.0f, 0.005f);
    f.someValue = 13;
}  

BOOST_AUTO_UNIT_TEST (TestCase2)
{
    MyFixture f;
    BOOST_CHECK_EQUAL (f.str, std::string(&#34;Hello&#34;));
    BOOST_CHECK_CLOSE (f.someValue, 2.0f, 0.005f);
    // Boost deals with this OK and reports the problem
    //f.myObject.UseBadPointer();
    // Same with this
    //myObject.DivideByZero();
}  

BOOST_AUTO_UNIT_TEST (TestCase3)
{
    MyFixture f;
    BOOST_CHECK_EQUAL (1, f.myObject.s_currentInstances);
    BOOST_CHECK_EQUAL (3, f.myObject.s_instancesCreated);
    BOOST_CHECK_EQUAL (1, f.myObject.s_maxSimultaneousInstances);
}
</code></pre><ol start="6">
<li><strong>Handles exceptions and crashes well.</strong> This is one of the aspects where Boost.Test is head and shoulders above all the competition. Not only does it handle exceptions correctly, but it prints some information about them, it catches Linux system exceptions, and it even has a command-line argument that disables exception handling, which allows you to catch the problem in your debugger on a second run. I really couldn&rsquo;t ask for much more.</li>
<li><strong>Good assert functionality.</strong> Yes. Has assert statements for just about any operation you want (equality, closeness, less than, greater than, bitwise equal, etc). It even has support for checking whether exceptions were thrown. The assert statements correctly print out the contents of the variables being checked. Top marks on this one.</li>
<li><strong>Supports different outputs.</strong> Probably, but it&rsquo;s not exactly trivial to change. At least the default output is IDE friendly. I suspect I would need to dig deeper into the unit_test_log_formatter, but I certainly didn&rsquo;t see a variety of preset output types that I could just plug in.</li>
<li><strong>Supports suites.</strong> Yes, but with a big catch. Unless I&rsquo;m missing something (which is very possible at this point&ndash;if so make sure to let me know), creating a suite requires a bunch of fairly verbose statements and also requires modifying the test runner itself in main. Have a look at the example below. Couldn&rsquo;t that have been simplified to the extreme? It&rsquo;s not a big deal as this is my least-wanted requirement, but I wish I could label all the test cases in one file as part of a suite with a simple macro at the beginning of the file. Another minor shortcoming is the lack of setup/teardown steps for whole suites, which could come in really handy (especially if suite creation were streamlined).</li>
</ol>
<pre tabindex="0"><code>#include &lt;boost/test/unit_test.hpp&gt;
#include &lt;boost/test/floating_point_comparison.hpp&gt;
using boost::unit_test::test_suite;   

struct MyTest
{
    void TestCase1()
    {
        float fnum = 2.00001f;
        BOOST_CHECK_CLOSE(fnum, 2.f, 1e-3);
    }

    void TestCase2()
    {}
};

test_suite * GetSuite1()
{
    test_suite * suite  = BOOST_TEST_SUITE(&#34;my_test_suite&#34;);
    boost::shared_ptr instance( new MyTest() );
    suite-&gt;add (BOOST_CLASS_TEST_CASE( &amp;MyTest::TestCase1, instance ));
    suite-&gt;add (BOOST_CLASS_TEST_CASE( &amp;MyTest::TestCase2, instance ));
    return suite;
}
</code></pre><pre tabindex="0"><code>#include &lt;boost/test/auto_unit_test.hpp&gt;
using boost::unit_test::test_suite; 

extern test_suite * GetSuite1();  

boost::unit_test::test_suite* init_unit_test_suite( int /* argc */, char* /* argv */ [] )
{
    test_suite * test = BOOST_TEST_SUITE(&#34;Master test suite&#34;);
    test-&gt;add( boost::unit_test::ut_detail::auto_unit_test_suite() );
    test-&gt;add(GetSuite1());
    return test;
}
</code></pre><p>Boost.Test is a library with a huge amount of potential. It has great support for exception handling and advanced assert statements. It also has other fairly unique functionality such as support for checking for infinite loops, and different levels of logging. On the other hand, it&rsquo;s very verbose to add new tests that are part of a suite, and it might be a bit heavy weight for game console environments.</p>
<p>CppUnitLite has a funny story behind it. <a href="http://www.objectmentor.com/aboutUs/bios/Michael%20Feathers">Michael Feathers</a>, the original author of CppUnit, got fed up with the complexity of CppUnit and how it didn&rsquo;t fit everyone&rsquo;s needs, so we wrote the ultra-light weight framework CppUnitLite. It is as light on the features as it is on complexity and size, but his philosophy was to let people customize it to deal with whatever they need.</p>
<p>Indeed, CppUnitLite is only a handful of files and it probably adds up to about 200 lines of very clear, easy to understand and modify code. To be fair, in this comparison I actually used a version of CppUnitLite I modified a couple of years ago (download it along with all <a href="/wp-content/uploads/bin/unit_test_frameworks.tar.gz">the sample code</a>) to add some features I needed (fixtures, exception handling, different outputs). I figured it was definitely in the spirit that CppUnitLite was intended, and if nothing else, it can show what can be accomplished by just a few minutes of work with the source code.</p>
<p>On the other hand, CppUnitLite doesn&rsquo;t have any documentation to speak of. Heck, it doesn&rsquo;t even have a web site of its own, which I&rsquo;m sure is not helping the adoption rate by other developers.</p>
<ol>
<li><strong>Minimal amount of work needed to add new tests</strong>. Absolutely! Of all the unit-test frameworks, this is the one that comes closest to the ideal. On the other hand, it could be the fact that I&rsquo;ve used CppUnitLite the most and I&rsquo;m biased. In any way, it really fits my idea of minimum amount of work required to set up a simple test or even one with a fixture (although that could be made even better).</li>
</ol>
<pre tabindex="0"><code>#include &#34;lib/TestHarness.h&#34;  

TEST (Whatever,MyTest)
{
    float fnum = 2.00001f;
    CHECK_DOUBLES_EQUAL (fnum, 2.0f);
}
</code></pre><ol start="3">
<li>
<p><strong>Easy to modify and port.</strong> Definitely. Again, it gets best of the class award in this category. No other unit-test framework comes close to being this simple, easy to modify and port, and at the same time having reasonably well separated functionality. The original version of CppUnitLite even had a special lightweight string class to avoid dependencies on STL. In my modified version I changed it to use std::string since that&rsquo;s what I use in most of my projects, but the change took under one minute to do. Also, using it under Linux was absolutely trivial, even though I had only used it under Windows before.</p>
</li>
<li>
<p><strong>Supports fixtures.</strong> This is where the original CppUnitLite starts running into trouble. It&rsquo;s so lightweight that it doesn&rsquo;t have room for many features. This was an absolute must for me, so I went ahead and added it. I&rsquo;m sure it could be improved to make it so adding a fixture requires even less typing, but it&rsquo;s functional as it stands. Unfortunately, it suffers from the problem that objects need to be created dynamically if we want them to be created right before each test. To be fair though, every single unit-test framework in this evaluation has that requirement. Oh well.</p>
</li>
</ol>
<pre tabindex="0"><code>#include &#34;lib/TestHarness.h&#34;
#include &#34;MyTestClass.h&#34;   

class MyFixtureSetup : public TestSetup
{
public:
    void setup()
    {
        someValue = 2.0;
        str = &#34;Hello&#34;;
    }
    void teardown()
    {}
protected:
    float someValue;
    std::string str;
    MyTestClass myObject;
};   

TESTWITHSETUP (MyFixture,Test1)
{
    CHECK_DOUBLES_EQUAL (someValue, 2.0f);
    someValue = 0;
    // CppUnitLite doesn&#39;t handle system exceptions very well either
    //myObject.UseBadPointer();
    // A regular exception works nicely though myObject.ThrowException();
}  

TESTWITHSETUP (MyFixture,Test2)
{
    CHECK_DOUBLES_EQUAL (someValue, 2.0f);
    CHECK_STRINGS_EQUAL (str, std::string(&#34;Hello&#34;));
}   

TESTWITHSETUP (MyFixture,Test3)
{
    // Unfortunately, it looks like the framework creates 3 instances of MyTestClass
    // right at the beginning instead of doing it on demand for each test. We would
    // have to do it dynamically in the setup/teardown steps ourselves.
    CHECK_LONGS_EQUAL (1, myObject.s_currentInstances);
    CHECK_LONGS_EQUAL (3, myObject.s_instancesCreated);
    CHECK_LONGS_EQUAL (1, myObject.s_maxSimultaneousInstances);
}
</code></pre><ol start="6">
<li>
<p><strong>Handles exceptions and crashes well.</strong> The original CppUnitLite didn&rsquo;t handle them at all. I added minor support for this (just an optional try/catch). To run the tests without exception support it requires recompiling the tests with a special define turned on, so it&rsquo;s not at slick as the command-line argument that Boost.Test features.</p>
</li>
<li>
<p><strong>Good assert functionality.</strong> Here is where CppUnitLite really shows its age. The assert macros are definitely the worst of the lot. They don&rsquo;t use a stream to print out the contents of their variables, so we need custom macros for each object type you want to use. It comes with support for doubles, longs, and strings, but anything else you need to add by hand. Also, it doesn&rsquo;t have any checks for anything other than equality (or closeness in the case of floating-point numbers).</p>
</li>
<li>
<p><strong>Supports different outputs.</strong> Again, the original only had one type of output. But it was very well isolated and it was trivial to add more.</p>
</li>
<li>
<p><strong>Supports suites.</strong> Probably the only framework that doesn&rsquo;t support suites. I never really needed them, but they would probably be very easy to add on a per-file basis.</p>
</li>
</ol>
<p>CppUnitLite is as barebones as it gets, but with a few modifications it hits the mark in all the important categories. If it had better support for assert statements, it would come very close to my ideal framework. Still, it&rsquo;s a worthy candidate for the final crown.</p>
<p>I had never heard of NanoCppUnit until <a href="http://c2.com/cgi/wiki?PhlIp">Phlip</a> brought it up. From reading the feature list, it really appeared to be everything that I wanted CppUnitLite to be, except that it was better and ready to work out of the box.</p>
<p>The first point against NanoCppUnit is the awful â€œpackagingâ€ of the framework. If you thought that CppUnitLite was bad (not having a web page of its own), well, at least you could download it as a zip file. For NanoCppUnit you actually have to copy and paste the five files that make up the framework from a web page. I&rsquo;m not kidding. That makes for some â€œlovelyâ€ formatting issues I might add. The documentation found in the web page wasn&rsquo;t exactly very useful either.</p>
<p>In any case, I continued my quest to get a simple test program up and running with NanoCppUnit. Out of the box (or out of the web page, rather) it&rsquo;s clearly aimed only at Windows platforms. I thought it would be trivial to fix, but changing it required more time than I thought at first (I personally gave up when I started getting errors buried three macros deep into some assert statement). Unlike CppUnitLite, the source code is not very well structured at all, full of ugly macros everywhere, making it not trivial to add new features like new output types. Unless I&rsquo;m totally mistaken, it even looks like it has sample code inside the test framework itself. Eventually I had to give up on running it under Linux, so my comments here are just best guesses by looking at the source code.</p>
<ol>
<li><strong>Minimal amount of work needed to add new tests</strong>. I think so. I&rsquo;m not sure it&rsquo;s possible to create a standalone test that is part of a global suite, but at least creating a suite doesn&rsquo;t require manual registration of every test. This is (probably) the simplest possible test with NanoCppUnit.</li>
</ol>
<pre tabindex="0"><code>struct MySuite:  TestCase { };  

TEST_(MySuite, MyTest)
{
    float fnum = 2.00001f;
    CPPUNIT_ASSERT_DOUBLES_EQUAL(fnum, 2.0f, 0.0001);
}
</code></pre><ol start="3">
<li><strong>Easy to modify and port.</strong> Not really. Windows dependencies run deeper than it seems on the surface. The code is small, but it&rsquo;s messy enough that it&rsquo;s a pain to work with. I&rsquo;m sure it can be ported with a bit of effort though since it&rsquo;s so small.</li>
<li><strong>Supports fixtures.</strong> Yes. Setup and teardown calls very similar to the modified version of CppUnitLite.</li>
<li><strong>Handles exceptions and crashes well.</strong> No idea since I wasn&rsquo;t able to run it. I see some try/catch statements in the code, but no way to turn them on or off. Probably no better than CppUnitLite.</li>
<li><strong>Supports different outputs.</strong> Not really. Everything is hardwired to use a stream that sends its contents to OutputDebugString() in Windows. I think the default output text is formatted to match the Visual Studio error format.</li>
<li><strong>Good assert functionality.</strong> Yes. Good range of assert statements, including floating point closeness, greater than, less than, etc.</li>
<li><strong>Supports suites.</strong> Yes. I don&rsquo;t know what&rsquo;s involved in just running a single suite though. Not a big deal either way.</li>
</ol>
<p>One of NanoCppUnit&rsquo;s unique features is regular expression support as part of its assert tests. That&rsquo;s very unusual, but I can see how it could come in handy. A few times in the past, I&rsquo;ve had to check that a certain line of code has some particular format, so I had to sscanf it, and then check on some of the contents. A regular expression check would have done the job nicely.</p>
<p>Unfortunately, NanoCppUnit doesn&rsquo;t really live up to the standards of other frameworks. Right now it feels too much as a work in progress, with too much missing functionality and not clearly structured code.</p>
<p>The further along we get in this evaluation, the less Xunit-like the frameworks become. Unit++&rsquo;s unique feature is that it pretends to be more C++-like than CppUnit. Wait a second, did I hear that right? More C++ like? Is that supposed to be a good thing? Looking back at my ideal test framework, it really isn&rsquo;t very much like C++ at all. Once I started thinking about that topic I realized that there really is no reason at all why the tests framework itself needs to be in C++. The tests you write need to be in the language of the code being tested, but all the wrapper code doesn&rsquo;t. That&rsquo;s a point that the next, and final, testing framework will drive home.</p>
<p>So, what does it mean to be more C++ like? No macros for a start. You create suites of tests by creating classes that derive from suite. That&rsquo;s the same thing we were doing in most other frameworks, really, but it was just happening behind the scenes. It really doesn&rsquo;t help me any to know that that is what I&rsquo;m doing, and I would certainly not call it a â€œfeature.â€ As a result, tests are more verbose than they could be.</p>
<p>The documentation is simply middle-of-the-road. It&rsquo;s there, but it&rsquo;s not particularly detailed and it doesn&rsquo;t come loaded with examples.</p>
<ol>
<li><strong>Minimal amount of work needed to add new tests</strong>. I&rsquo;m afraid it gets failing marks for this. It requires manual registration of tests, and every test needs to be part of a suite. This makes adding new tests tedious and error prone (by writing a new test and forgetting to register it). I don&rsquo;t know about you, but with all the C++ cruft, I look at the code below and it&rsquo;s not immediately obvious what it does until I&rsquo;ve scanned it a couple of times. The signal to noise ratio is pretty poor.</li>
</ol>
<pre tabindex="0"><code>#define __UNITPP #include &#34;unit++.h&#34;
using namespace unitpp;
namespace
{
    class Test : public suite
    {
        void test1()
        {
            float fnum = 2.00001f;
            assert_eq(&#34;Checking floats&#34;, fnum, 2.0f);
        }
    public:
        Test() : suite(&#34;MySuite&#34;)
        {
            add(&#34;test1&#34;, testcase(this, &#34;Simplest test&#34;, &amp;Test::test1));
            suite::main().add(&#34;demo&#34;, this);
        }
    }; 

    Test* theTest = new Test();
}
</code></pre><ol start="3">
<li><strong>Easy to modify and port.</strong> So-so. It needs the STL and it pulls in some stuff like iostreams (which I remember having distinct problems with when I was working with STLPort). On the other hand the source code is relatively small and self-contained so it&rsquo;s certainly doable to port and modify if you&rsquo;re willing to put in some time.</li>
<li><strong>Supports fixtures.</strong> Another framework that I just can&rsquo;t see how to do fixtures with. Like Boost.Test, it seems to think that using the constructor and destructor for each class is all you need. A quick search for fixture or setup or teardown in the documentation doesn&rsquo;t reveal anything. I don&rsquo;t know if I&rsquo;m totally missing something or if other people just write very different tests from me. I suppose I could create a new class for every fixture I want, put the setup in the constructor and the teardown in the destructor and inherit from it for every test case (and somehow figure out how to create an instance of that class and use it for each test run). It&rsquo;s probably possible, but it&rsquo;s not exactly trivial, is it? Again, the lack of fixtures puts this framework out of the running.</li>
<li><strong>Handles exceptions and crashes well.</strong> Average. It manages to catch regular exceptions without crashing, but that&rsquo;s about it. No system exceptions in Linux. No way to turn it off for debugging.</li>
<li><strong>Supports different outputs.</strong> I couldn&rsquo;t figure out how to do it from the documentation. There is probably a way to do it since it even supports GUI functionality , but it&rsquo;s not obvious (and there are no examples). Besides, by this point, having failed points 1 and 3, I wasn&rsquo;t really motivated to spend a while learning the framework. Incidentally, this is one of the few frameworks whose default text output is not formatted correctly for IDEs like KDevelop.</li>
<li><strong>Good assert functionality.</strong> It scrapes by with the minimum in this department. It provides equality and condition checks, but that&rsquo;s it. It doesn&rsquo;t even provide a float version of assert to check for â€œclose enough.â€ At least it prints the contents of the variables to a stream correctly.</li>
<li><strong>Supports suites.</strong> Yes, like most of them.</li>
</ol>
<p>Overall, Unit++ is not really a candidate. Perhaps it&rsquo;s because it&rsquo;s not intended for the type of testing I intend to use it for, but it doesn&rsquo;t offer anything new over other frameworks and it has a lot of drawbacks of its own. The lack of fixtures is simply unforgivable.</p>
<p>After looking into a framework that tried to be different from XUnit (Unit++), I wasn&rsquo;t particularly looking forward to evaluating possibly the wackiest one of them all, CxxTest. I had never heard of it until a few days ago, but I knew that it required using Perl along the way to generate some C++ code. My spider senses were tingling.</p>
<p>Boy was I wrong!! Within minutes of using CxxTest and reading through its great documentation (the best by far), I was completely convinced this was the way to go. This came as a complete surprise to me since I was ready to leave somewhat dissatisfied and pronounce a victor between CppUnit and CppUnitLite.</p>
<p>Let&rsquo;s start from the beginning. What&rsquo;s with the use of Perl and why is it different from CppUnit? Erez Volk, the author of CxxTest, had the unique insight that just because we&rsquo;re testing a C++ program, we don&rsquo;t need to rely on C++ for everything. Other languages, such as Java, are better suited to what we want to do in a unit-testing framework because they have good introspection (reflection) capabilities. C++ is quite lacking in that category, so we&rsquo;re forced to use kludges like manual registration of tests, ugly macros, etc. CxxTest gets around that by parsing our simple tests and generating a C++ test runner that calls directly into our tests. The result is simply brilliant. We get all the flexibility we need without the need for any ugly macros, exotic libraries, or fancy language features. As a matter of fact, CxxTest&rsquo;s requirements are as plain vanilla as you can get (other than being able to run Perl).</p>
<p>The code-generation step is also trivial to integrate into the regular build system. The wonderful documentation gives explicit step-by-step instructions on how to integrate it with make files, Visual Studio projects files, or <a href="http://www.dsmit.com/cons/">Cons</a>. Once you have it set up, you won&rsquo;t even remember there&rsquo;s anything out of the ordinary going on.</p>
<p>Let&rsquo;s see how it stacks up against the competition.</p>
<ol>
<li><strong>Minimal amount of work needed to add new tests</strong>. Very good. It&rsquo;s almost as simple as the best of them. If I could nit-pick, I would have wished for an even simpler way to create tests without the need to declare the class explicitly. Since we&rsquo;re doing processing with a Perl script, there&rsquo;s no reason we couldn&rsquo;t have taken it a step beyond that and used a syntax even closer to my ideal test framework.</li>
</ol>
<pre tabindex="0"><code>class SimplestTestSuite : public CxxTest::TestSuite
{
    public: void testMyTest()
    {
        float fnum = 2.00001f;
        TS_ASSERT_DELTA (fnum, 2.0f, 0.0001f);
    }
};
</code></pre><ol start="3">
<li><strong>Easy to modify and port.</strong> CxxUnit requires the simplest set of language features (no RTTI, no exception handling, no template functions, etc). It also doesn&rsquo;t require any external libraries. It is also distributed simply as a set of header files, so there&rsquo;s no need to compile into a separate library or anything like that. Functionality is pretty well broken down and separated in the original source code, so making modifications should be fairly straightforward.</li>
<li><strong>Supports fixtures.</strong> CxxUnit gets the â€œtop of its classâ€ label in this category. Not only does it support setup/teardown steps on a per-test level, but it also supports them at the suite and at the world (global) level. Creating fixtures is pretty straightforward and just requires inheriting from a class and creating as many functions as you want starting with the letters â€œtest.â€ To be really picky, I would have loved it if they had taken it a step further and, apart from simplifying the code a bit more, also inserted the setup and teardown code around the code for each test. That would have allowed us to work with those objects directly on the stack and their lifetime would have been managed correctly around each test. Oh well. Can&rsquo;t have everything.</li>
</ol>
<pre tabindex="0"><code>#include &#34;MyTestClass.h&#34;  

class FixtureSuite : public CxxTest::TestSuite
{
public:
    void setUp()
    {
        someValue = 2.0;
        str = &#34;Hello&#34;;
    } 

    void tearDown() {}  

    void test1()
    {
        TS_ASSERT_DELTA (someValue, 2.0f, 0.0001f);
        someValue = 13.0f;
        // A regular exception works nicely though myObject.ThrowException();
    } 

    void test2()
    {
        TS_ASSERT_DELTA (someValue, 2.0f, 0.0001f);
        TS_ASSERT_EQUALS (str, std::string(&#34;Hello&#34;));
    } 

    void test3()
    {
        //myObject.UseBadPointer();
        TS_ASSERT_EQUALS (1, myObject.s_currentInstances);
        TS_ASSERT_EQUALS (3, myObject.s_instancesCreated);
        TS_ASSERT_EQUALS (1, myObject.s_maxSimultaneousInstances);
    }  

    float someValue;
    std::string str;
    MyTestClass myObject;
};
</code></pre><ol start="6">
<li><strong>Handles exceptions and crashes well.</strong> Great support. It catches all exceptions and prints information about them formatted like any other error (no system exceptions under Linux though). You can easily re-run the tests with a command-line argument to the Perl script to avoid catching exceptions and catch them in the debugger instead. It also gives you a custom version of every assert macro that lets you catch the exceptions yourself in case you ever need to do that.</li>
<li><strong>Supports different outputs.</strong> Different outputs are supported by passing a parameter indicating which type of output you want to the Perl processing step. The default one (error-printer) was formatted correctly for IDE parsing, and you can use several others (including GUIs for those of you addicted to progress bars, a yes/no report, or a stdio one). Adding new output formatting sounds very straightforward and it&rsquo;s even covered in the documentation.</li>
<li><strong>Good assert functionality.</strong> Again, it gets â€œtop of its classâ€ for this one. It has a whole suite of very comprehensive assert functions, including ones for exception handling, checking predicates, and arbitrary relations. It even has a way to print out warnings which can be used to differentiate between two parts of the code calling the same test, or to print reminder â€œTODOâ€ messages to yourself.</li>
<li><strong>Supports suites.</strong> Yes. All tests are part of a suite.</li>
</ol>
<p>Another feature supported by CxxUnit that I haven&rsquo;t had time to look into is some support for <a href="http://www.mockobjects.com/FrontPage.html">mock objects</a>. Anybody doing TDD knows the value of mock objects when it comes to testing the interactions between a set of objects. Apparently CxxUnit allows you to override global functions with specific mock functions (it gives an example of overriding fopen()). I don&rsquo;t think it helps any with regular classes; for those you&rsquo;re on your own.</p>
<p>So, what&rsquo;s not to like in CxxTest? Not much, really. Other than wishing that the test syntax were a bit tighter, the only thing to watch out for is what happens with large projects. If you follow the examples in the documentation, it will create a single runner for all the tests you give it. This can be problematic if you&rsquo;re going to be having thousands of tests, and then making one small change in one of them causes a full recompilation of all your code.</p>
<p><strong>Update</strong>: After talking with Erez and re-checking the documentation, I realized this is already fully supported in CxxUnit. By default, when you generate a test runner, it adds a main function and some global variables, so linking with other similar runners gives all sorts of problems. However, it turns out you can generate a test runner with the &ndash;part argument, and it will leave out the main function and any other globals. You can then link together all the runners and have a single executable. I wonder if it would be worth going as far as creating a runner for every suite, or if it would be best to cluster suites together. Worth investigating at some point whenever I get enough tests to make a difference.</p>
<p><strong>Conclusion</strong></p>
<p>After going through all six C++ unit-testing frameworks, four stand out as reasonable candidates: CppUnit, Boost.Test, a modified CppUnitLite, and CxxTest.</p>
<p>Of the four, CxxTest is my new personal favorite. It fits very closely the requirements of my ideal framework by leveraging the power of an external scripting language. It&rsquo;s very usable straight out of the â€œboxâ€ and it provides some nifty advanced features and great assert functionality. It does require the use of a scripting language as part of the build process, so those unconfortable with that requirement, might want to look at one of the other three frameworks.</p>
<p>CppUnit is a solid, complete framework. It has come a long, long way in the last few years. The major drawbacks are the relative verbosity for adding new tests and fixtures, as well as the reliance on STL and some advanced language issues.</p>
<p>If what you need is absolute simplicity, you can do no wrong starting with CppUnitLite (or a modified version), and tweaking it to fit your needs. It&rsquo;s a well-structured, ultra-light framework with no external dependencies, so modifying it is extremely easy. Its main drawback is the lack of features and the primitive assert functionality.</p>
<p>If you&rsquo;re going to be working mostly on the PC, you don&rsquo;t expect to have to modify the framework itself, and you don&rsquo;t mind pulling in some additional Boost libraries, Boost.Test could be an excellent choice.</p>
<p>Should you roll your own unit-test framework? I know that Kent Beck recommends it in his book <a href="http://www.amazon.com/exec/obidos/ASIN/0321146530/ref=nosim/gamesfromwith-20"><em>Test-Driven Development: By Example</em></a>, and it might be a great learning experience, but I just can&rsquo;t recommend it. Just as it&rsquo;s probably good to write a linked-list and a stack data structure a few times but I wouldn&rsquo;t recommend actually doing that in production code instead of using the ones provided in the STL, I strongly recommend starting with one of the three unit-testing frameworks mentioned above. If you really feel the need to roll your own, grab CppUnitLite and get hacking.</p>
<p>Whichever one you choose, you can really do no wrong with one of those three frameworks. The most important thing is that you are writing unit tests, or, even better, doing test-driven development. To paraphrase Michael Feathers, code without unit tests is legacy code, and you don&rsquo;t want to be writing legacy code, do you?</p>
<p><a href="/wp-content/uploads/bin/unit_test_frameworks.tar.gz"><img alt="icon" loading="lazy" src="/exploring-the-c-unit-testing-framework-jungle/images/script.png"> unit_test_frameworks.tar.gz</a></p>]]></content:encoded></item><item><title>Book review: Effective STL</title><link>https://gamesfromwithin.com/book-review-effective-stl/</link><pubDate>Sat, 13 Nov 2004 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/book-review-effective-stl/</guid><description>&lt;p&gt;Have you read &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0201924889/ref=nosim/gamesfromwith-20"&gt;&lt;em&gt;Effective C++&lt;/em&gt;&lt;/a&gt; also by Scott Meyers? No? Go buy it right now, read it, reread it, and then come back here. I guarantee that it will make a huge difference in the way you work.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Have you read <a href="http://www.amazon.com/exec/obidos/ASIN/0201924889/ref=nosim/gamesfromwith-20"><em>Effective C++</em></a> also by Scott Meyers? No? Go buy it right now, read it, reread it, and then come back here. I guarantee that it will make a huge difference in the way you work.</p>
<p>This review was first published in the January 2002 issue of Game Developer Magazine. <a href="http://www.convexhull.com/articles/gdmag_effective_stl.pdf">Printer-friendly format</a>.</p>
<p><a href="http://www.amazon.com/Effective-STL-Addison-Wesley-Professional-Computing/dp/0201749629%3FSubscriptionId%3D02E5W5871AJF7PMMMS82%26tag%3Dgamesfromwith-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0201749629"><img loading="lazy" src="/book-review-effective-stl/images/41W3B0YFG8L._SL500_.jpg"></a></p>
<p>OK, welcome back. Here is the good news: <em>Effective STL</em> is to STL what <em>Effective C++</em> is to C++. It&rsquo;s equally great and it&rsquo;s written in the same light, conversational Scott Meyers style that makes reading it a pleasure. It assumes that you have basic knowledge of STL (and C++) and builds on that to show you how to use it effectively and avoid common pitfalls.</p>
<p>Those of you unfamiliar with STL must be wondering what it is and how is it useful for game development. STL stands for Standard Template Library: A library of generic data structures and algorithms that you can use across many compilers/platforms, including most of the current consoles. The library is implemented with templates so the resulting code will be quite efficient, possibly even more than your hand-coded structures and algorithms. Additionally, it has been implemented, tested, debugged and optimized by thousands of people, so it&rsquo;s code you can usually rely on. STL also empowers you by putting very powerful constructs at your fingertips. Maybe before you would have thrown a bunch of objects in an array and searched through them in linear time (does that sound familiar?), but now you can just as easily put them in a hash table and have constant-time access to them.</p>
<p><em>Effective STL</em> starts out with a fairly thorough discussion about containers (vector, list, map, etc) and iterators. It immediately goes beyond the typical description of the containers and their O(n) performance characteristics. Instead it deals with many real-world questions: Is the memory for the elements allocated contiguously? Are the iterators invalidated when the elements change? What the most efficient way of removing elements for a specific container? Those are not issues you&rsquo;ll see addressed in most STL books.</p>
<p>It then moves on to algorithms and functors. Just like with the containers, instead of listing all the available algorithms, it points out common mistakes and how to deal with them. For example, it will discuss the different ways of sorting elements, or how std::remove really works (and why it doesn&rsquo;t really remove anything).</p>
<p>The final chapters present more general, but very useful, information on the STL that will save you a few headaches along the way: When to use STL algorithms and when to use your own, style guidelines, or even how to deal with Microsoft&rsquo;s Visual C++ broken STL implementation and template support.</p>
<p>But STL is not perfect. Reading the book will give you some ideas of where STL is lacking, but it won&rsquo;t spell them out for you. Sometimes you&rsquo;ll need to read between the lines and think about how things will apply to game development. For example, memory allocation can be an issue, especially if you&rsquo;re developing for a console, so you&rsquo;ll probably want to end up writing your own allocators. The book has a brief couple of items discussing what you can and can&rsquo;t do with allocators, but not enough to write your own. You&rsquo;ll need to look elsewhere for that.</p>
<p>Another issue often brought up when dealing with STL is the difficulty debugging STL code, from cryptic multi-line error messages to the difficulty viewing the elements of a container in the debugger. The book will help you a bit by showing you how to â€œparseâ€ the intimidating error messages and directs you to some STL resources on the Internet.</p>
<p><em>Effective STL</em> works very well both as a book to read cover to cover and as a reference later on. It only uses source code where it has to; it won&rsquo;t bore you with pages and pages of pointless code. As a matter of fact, it won&rsquo;t bore you at all since it packs a lot of information in a mere 250 pages. Overall, you simply must read this book before you decide to use (or not to use) STL in your next game or tools. If you&rsquo;re already using STL, then it should already be on your bookshelf.</p>]]></content:encoded></item><item><title>Simple Is Beautiful</title><link>https://gamesfromwithin.com/simple-is-beautiful/</link><pubDate>Thu, 17 Jun 2004 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/simple-is-beautiful/</guid><description>&lt;p&gt;If you&amp;rsquo;ve read some of &lt;a href="https://gamesfromwithin.com/maintenance-the-hidden-cost-of-software/%20"&gt;my other articles&lt;/a&gt;, you know that I believe that the best code is no code at all. But what if you actually have to write some code? What then? This article deals with that question and shows the importance of simplicity.&lt;/p&gt;</description><content:encoded><![CDATA[<p>If you&rsquo;ve read some of <a href="/maintenance-the-hidden-cost-of-software/%20">my other articles</a>, you know that I believe that the best code is no code at all. But what if you actually have to write some code? What then? This article deals with that question and shows the importance of simplicity.</p>
<p>As I write this there are still a few cardboard boxes strewn across our home as we finish unpacking everything. My wife and I just finished a surprisingly painless cross-country move to <a href="http://www.sannet.gov/">sunny San Diego</a>. The town house we&rsquo;re moving into is definitely larger than our previous condo, but it wasn&rsquo;t until we had to pack everything, move it, and then unpack it that we realized how much stuff we had accumulated over the years. Yes, there was a reason for everything we had, but it was still a lot of stuff. Then we came to the realization that we prefer a more open, simpler environment with fewer pieces of furniture, fewer paintings covering the walls, and less clutter in general.</p>
<p>That is an interesting insight because it applies to many different things, including programming: There is a cost associated with having a complex, cluttered environment, whether it be the furniture in your house, your class hierarchy, or your build process. In particular it will create resistance to change, which can be in the form of a cross-country move, or a simple class refactoring.</p>
<h3 id="goals">Goals</h3>
<p>The ultimate reason to write code is to have the computer carry out a sequence of instructions. In our case, that sequence of instructions is a game or a tool to help create the game. It is tempting to think of the computer as the â€œaudienceâ€ for our program, but it is not a very good audience. It is way too forgiving, and as long as things compile, it&rsquo;ll be happy with anything you throw at it. We can do better than that.</p>
<p>We can still write code that is correct, but with people in mind as the primary audience. The usual reason for choosing people as your audience is that software development is a team effort, and it&rsquo;s very important that other people be able to understand and modify your code. True, but there&rsquo;s more to it than that. Even if you were the only person writing code, you should still write for people, not computers. Assuming it&rsquo;s more than a toy project, you will have to refactor your code as you learn new things about it. Probably not once, not twice, but many times over the course of the project&rsquo;s lifetime. You will have to keep it up to date, fix bugs, add new features, etc. I am convinced that refactoring (or lack thereof) is one of the major influences on code quality, and, as a consequence, product quality, so anything to help with that is extremely important in my book.</p>
<p>Lately, I&rsquo;ve been taking it a step further and thinking of my audience not just other programmers, but other people who are not programmers. If you manage to write some code that a non-programmer can more or less understand, then you know you&rsquo;re there. The code should be simple and self-explanatory enough that should be a breeze to refactor in the future.</p>
<p><img alt="links (c) freeimages.co.uk" loading="lazy" src="/simple-is-beautiful/images/abstractlinks_1.jpg"></p>
<p>But wait, as if ease of refactoring wasn&rsquo;t enough, there are more reasons for writing really simple code. <a href="http://www.cs.utexas.edu/users/EWD/">Edsger W. Dijkstra</a> in his lecture <a href="http://www.cs.utexas.edu/users/EWD/ewd03xx/EWD340.PDF">â€œThe Humble Programmerâ€</a> advocated the avoidance of clever tricks and urged programmers to be fully aware of the limitations of the human mind when writing programs.</p>
<p>&ldquo;The competent programmer is fully aware of the strictly limited size of his own skull; therefore he approaches the programming task in full humility, and among other things he avoids clever tricks like the plague.&rdquo;</p>
<p>Dijkstra&rsquo;s reason for keeping clever tricks away is not so much for ease of refactoring, but the quality of the program itself. Programmers are all too eager to tackle something too ambitious at once, without breaking it down into smaller, more understandable sub-problems, and, as a result, create a disastrous program that crashes often and doesn&rsquo;t even implement all the required features.</p>
<p>Today, this sounds like a surprisingly modern attitude. After all, it&rsquo;s right up the alley of agile development. But amazingly, this lecture took place in 1972. Talk about timeless advice (OK, OK, in the really short scale of computer history, not in the grand scheme of things).</p>
<p><a href="http://cm.bell-labs.com/cm/cs/who/bwk/">Brian Kernighan</a> had also something to contribute to the idea of writing simple code, but coming from a very different angle:</p>
<p>&ldquo;Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.&rdquo;</p>
<p>While I totally agree with the sentiment, I feel it is not as important as the other two reasons for aiming towards code simplicity. Frankly, if you use test-driven development and take steps of the correct size, you should hardly ever find yourself knee-deep in the debugger trying to make sense of your program. However, a decade or two ago that made a lot more sense, especially given that debuggers were less sophisticated then as well. Still, anything that encourages programmers to keep things simple is a step in the right direction. So if that convinces some people, so be it.</p>
<h3 id="attaining-simplicity">Attaining Simplicity</h3>
<p>Great. Simple is good. How do we write â€œsimpleâ€ code? That&rsquo;s not something they teach in school and it&rsquo;s not something that is pushed for in the workplace, so it&rsquo;s probably not something you&rsquo;re used to thinking about. The rest of the article will be a series of suggestions and techniques on how to make code as simple as possible. Specific examples are given in C++, but the general techniques should apply to most object-oriented languages.</p>
<p><strong>Avoid unnecessary language tricks.</strong></p>
<p>Listen to Dijkstra and go easy on â€œclever code.â€ If you feel the need to write a comment to explain to other people what that cute line of code you just wrote does, you should very strongly consider re-writing it so a comment is not necessary. I&rsquo;m not saying to avoid taking advantage of language features, just the ones that can be done in another, simpler way. For example, don&rsquo;t use a template when a non-templated implementation is perfectly fine. Don&rsquo;t rely on a clever arrangement of variables so they&rsquo;re initialized in the correct order even though the language standard says it should work.</p>
<p><strong>Avoid or postpone performance optimizations that obscure the meaning of the code for as long as possible.</strong></p>
<p>You&rsquo;re all familiar with the Donald Knuth quote: â€œPremature optimization is the root of all evil.â€ Programs have a way of twisting into evil, misshapen fiends when they&rsquo;re optimized, and they usually become much harder to refactor afterwards. Specifically in this case, I suggest avoiding (or delaying at least) optimizations that affect how simple or readable a section of code is. There are many ways to skin a cat, and there are also many ways to optimize a program. I find that there is often a way to optimize things that doesn&rsquo;t cause a major loss in code simplicity. But if that&rsquo;s not possible, at least defer that optimization as long as possible. Maybe you won&rsquo;t need it, and maybe the code will change before then and you&rsquo;ll save yourself a lot of rework.</p>
<p><strong>Functions should do one thing only.</strong></p>
<p>The secret to a good function is that it should do one thing and one thing only. Functions that follow that rule are usually quite small (at most 10-15 lines in C++) and their whole meaning can be easily understood at a glance. Because the function has only one purpose, refactoring becomes very easy: No need to worry about how changes in that function will affect other parts of the function, no pesky local variables reused in many parts of the function, etc.</p>
<p>Maybe this is a bit extreme, but ideally, functions should be so simple that I should be able to look at a function, delete it and re-write it from scratch without any difficulty.</p>
<p>I follow two guidelines to keep functions as simple as possible:</p>
<ul>
<li>If a function goes over 10 to 15 lines of code, I look at it really hard and try to split it. Chances are it&rsquo;s doing more than one thing.</li>
<li>If I ever feel the need to write an explanatory comment about what a few lines of code do, I move those lines into a function of their own and give it a name that explains what it does (usually the same as the what the comment would have been). By following this rule, the only comments in my code are the ones that explain *why* the code does things the way it does, and deal with higher-level such as the purpose of a class or a library.</li>
</ul>
<p><strong>Classes should do one thing only.</strong></p>
<p>This should come as no big surprise. If we want our functions to be small, simple, and just one thing, we also want the same qualities from our classes. When classes are left unchecked, they can easily grow into unmanageable blobs of many thousands of lines. The largest class I had the misfortune of encountering had a staggering 10,000 lines in it, and the problem was compounded by inheriting from another class with over 8,000 lines! As you can imagine, having to do any work near that class was quite a punishment.</p>
<p><img alt="links (c) freeimages.co.uk" loading="lazy" src="/simple-is-beautiful/images/abstractlinks_2.jpg"></p>
<p>Personally, I feel that C++ classes should ideally be no more than about 200-300 lines (remember, with virtually no other comments). Anything that goes beyond that, and I start thinking hard about what exactly the class does. If a class reaches 1000 lines, it&rsquo;s time to get the axe out.</p>
<p>One technique I&rsquo;ve been following to keep classes as simple as possible is to use the <a href="http://www.cuj.com/documents/s=8042/cuj0002meyers/">controversial suggestion</a> from <a href="http://www.aristeia.com/">Scott Meyers</a> on how to decide on the scope of a function. The quick summary is that functions should be pushed out of a class as much as possible: if a function can be implemented as a non-member function, then do it; if it can be a class static, make it so; otherwise, leave it as a member function.</p>
<p>One immediate consequence of following that advice is that a class is stripped of anything that is not essential. Helper functions (both public and private to the class) are pushed out, and the meaning of the class is made more clear. The second consequence is that refactoring is a lot easier. By using non-member functions in anonymous namespaces whenever possible, we avoid the need to edit any header files at all, which results in faster compile and iteration times. Also, since those functions are completely independent of the class, they&rsquo;re trivial to move around, promote to higher levels, etc. while member functions require some massaging to move around.</p>
<p>I&rsquo;m suggesting that we keep functions small, but also that we keep classes small. We&rsquo;re not going to end up with any less code than we would have before, but we&rsquo;re going to end up with many more classes scattered all over our program. We have pushed the complexity from the function and class level up to the program organization and architecture level. The next article in this series will deal with how to manage this newfound complexity, but here&rsquo;s a preview: Use hierarchies.</p>
<p><strong>Timings, logging, and error handling</strong></p>
<p>Ideally, I&rsquo;d like my code to be really small, simple, and to the point so its meaning is always clear and obvious. Unfortunately, in the real world, that&rsquo;s is not always possible. We can start with a very clean 5-line function, but then we add timings around it to get an idea of its performance, and logging statements to know what is going on, and error handling code to deal with the unexpected, and before we know it, we have a monster function whose meaning is lost in a mass of details.</p>
<p>What can we do about it? We could argue that timings should be done with non-intrusive methods such as using profilers, but that&rsquo;s not always possible or desirable. We often want very specific timings that only affect a particular section of the code (load times), or we want to continuously monitor performance of certain sections while the game is running. For example, we probably want to get an idea of how much time we&rsquo;re spending each frame on each of the major tasks: entity updates, AI calculations, physics, animation, rendering, sound, etc. We need to wrap each of those areas in timing statements. The more detailed we want those timings to be, the more junk we&rsquo;ll have to add to the code. We can try making that as clean as possible by using macros that only require one line, but it&rsquo;s still junk that obscures the meaning.</p>
<p>Logging doesn&rsquo;t even have a non-intrusive counterpart unless you want to automatically add prologue and epilogue code to every function (which would generate way too many messages and would affect performance too much). So we&rsquo;re stuck writing messages by hand to the log system.</p>
<p>Error handling at least as has the possibility of using exceptions, which add a lot less clutter than returning and checking error codes. Unfortunately, we have to deal with several real-world issues which often make exception-handling impractical. The first one is performance. As much as I hate bringing this up, exception handling can easily have a significant performance impact even in modern hardware. This is something that will hopefully go away in the near future as PC hardware and consoles become more powerful. The second problem is compiler support. Even today, some console manufacturers are admitting that exception-handling support in their compilers is not usable and we shouldn&rsquo;t rely on it. So much for that idea. Finally, and probably most importantly, is complexity and programmer knowledge. If you have read <a href="http://www.amazon.com/exec/obidos/ASIN/0201615622/ref=nosim/gamesfromwith-20">Exceptional C++</a> you how complicated it can be to write exception-safe code, and not every C++ programmer out there today is going to feel comfortable using exceptions. All of this is a vicious circle, because until programmers demand robust and efficient exception handling, compiler and system creators aren&rsquo;t going to provide them, which means a lot of programmers are not going to be exposed to them, etc, etc.</p>
<p>So, what great solutions do I have to this problem? None, I&rsquo;m afraid. This is where I&rsquo;d like to hear from some of you. How do <strong>you</strong> deal with timing, logging, and error handling in a way to minimize the clutter and leave your code as clear as possible? Email me and I&rsquo;ll edit this article or make a new one with any great solutions I receive.</p>
<h3 id="striking-a-balance">Striking a balance</h3>
<p>In the end, even if we have the best goals in mind about simplicity, we will be forced to make compromises. Error handling is one case. Another case is often performance. Sometimes, having many scattered functions can add up to a noticeable performance hit in some inner loop of a performance-critical section. In that case simplicity needs to give way to practicality and do whatever is necessary. Just make really sure that having many functions is the cause of the performance problems before you make any changes.</p>
<p>It is also important not to confuse code simplicity with algorithmic simplicity. Writing simple code doesn&rsquo;t mean that you have to use a silly bubble sort to order a list. Always choose the most appropriate algorithm for the task at hand, just implement it with the simplest possible code. Implementing it in a very simple way will also make possible to easily change it down the line with a more efficient algorithm.</p>
<p>The next article will deal with how to manage all the complexity we&rsquo;ve pushed up into the program structure. Until then, keep your functions short, your classes clean, and remember The Humble Programmer:</p>
<p>&ldquo;&hellip;We shall do a much better programming job, provided that we approach the task with a full appreciation of its tremendous difficulty, provided that we stick to modest and elegant programming languages, provided that we respect the intrinsic limitations of the human mind and approach the task as Very Humble Programmers. &quot;</p>]]></content:encoded></item><item><title>Physical Structure and C++ - Part 2: Build Times</title><link>https://gamesfromwithin.com/physical-structure-and-c-part-2-build-times/</link><pubDate>Wed, 10 Mar 2004 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/physical-structure-and-c-part-2-build-times/</guid><description>&lt;p&gt;For small projects, we can blissfully code away without paying any attention to physical structure and we won&amp;rsquo;t be any worse off for it. However, as a project grows, it reaches a critical point where build times become unbearably slow. This article looks into the reasons for such slow build times and explores some techniques to speed things up.&lt;/p&gt;</description><content:encoded><![CDATA[<p>For small projects, we can blissfully code away without paying any attention to physical structure and we won&rsquo;t be any worse off for it. However, as a project grows, it reaches a critical point where build times become unbearably slow. This article looks into the reasons for such slow build times and explores some techniques to speed things up.</p>
<p>You know one of the reasons I refuse to live near most cities in the US? Traffic. I&rsquo;m not talking about the &ldquo;this road is crowded&rdquo; type of traffic that lets you zip along at a good speed, or even about the &ldquo;I can&rsquo;t get out of my lane because this is so packed&rdquo; type of traffic that moves slowly along. No, I&rsquo;ve come to accept and deal with that. It&rsquo;s the &ldquo;we might as well get out of the car and enjoy the sunshine because we aren&rsquo;t moving&rdquo; type of traffic that I can&rsquo;t stand. Amazingly enough, it seems to happen around most major cities in the US during rush hour, and sometimes this &ldquo;rush hour&rdquo; stretches from 7AM until 8PM. It&rsquo;s a bad sign when car manufacturers have advertisements telling you how much more comfortable you&rsquo;ll be in their car when you&rsquo;re stuck in traffic. Under those conditions it can easily take over an hour just to cover a distance of 3 or 4 miles.</p>
<p>Other than pointing out that you&rsquo;re much better off walking, cycling, or using public transportation, what&rsquo;s the point of all this and how does it relate to the physical structure of a program? There are some things that just don&rsquo;t scale well. They appear to work perfectly fine for a small number of units, but as soon as a certain threshold is reached, things seem to bog down and eventually collapse under their own weight. Just adding more lanes doesn&rsquo;t appear to solve the problem either, judging by the number of clogged-up 5-lane highways everywhere. Sometimes, you need to take a step back and deal with the problem in a different way. Either that, or buy a nice music system and enjoy your time in traffic.</p>
<p>We might not have much of a say over how traffic should be dealt with where we live, but we certainly have a lot of choices when it comes down to structuring our C++ source code. For small projects, we can blissfully code away without paying any attention to physical structure and we won&rsquo;t be any worse off for it. However, as a project grows, it reaches a critical point, and compilation times start getting slower and slower, to the point where tiny changes could make you wish you were stuck in traffic instead of staring powerlessly at your monitor. Adding a faster CPU, more memory, or a better hard drive can help make things faster, but is usually not a good long-term solution.</p>
<h3 id="build-types">Build Types</h3>
<p>We are usually concerned with the time for two types of builds:</p>
<ul>
<li>Full builds. In this case we care about the time it takes to build the whole project from scratch, starting from a totally clean build. This situation comes about when we just want to use the result of the build of a project we&rsquo;re not actively modifying. For example, an automated build machine will most likely be doing full builds of the game, so the turnaround time before a build is ready will depend on the full build time. Another example might be if you need to link your code with a library for which you have the source code.</li>
<li>Minimal builds. Once we have done a full build on a project, we then make a very small change to its source code and build it again. That&rsquo;s the time for a minimal build. This is what you really care about when you&rsquo;re actively working on a project, making modifications and compiling constantly. Ideally, building the project after a small change should require very little time This allows for very fast turnaround time for debugging, or even to get feedback from the compiler on silly syntax errors we just typed.</li>
</ul>
<p>Improving the physical structure of a program often reduces the time of both types of builds. Unfortunately things don&rsquo;t always work out so neatly and there are times where some changes will make one type of build faster and the other slower. Understanding what affects each compilation time allows us to optimize our compilation strategy and strike a balance that fits our needs.</p>
<p>Clearly, the time for both types of builds depends on the number of files and the complexity of those files. Both types of builds are also affected by the number of files each file depends on (the number of #include statements in each file). However, as we&rsquo;ll see in a moment, in the case of a full build there is the chance of caching the includes of some files and reusing them for other files.</p>
<p>There is something very different about minimal builds. Their build time is usually dominated by the number of files that depend on the modified files. In the worst situation, every file will depend on the file that changed and a full build will be triggered. In the ideal case, only the file with the changes itself will be compiled and no other files will have been affected. In one case the build could take less than a second, and in the other it could easily take multiple hours.</p>
<p>The rest of this article will look at different techniques to reduce build times and how they affect each of those two build types.</p>
<h3 id="counting-includes">Counting Includes</h3>
<p>It is easy to underestimate how quickly include statements can compound. If file A includes file B, and file B includes file C and D, every time someone includes file A they&rsquo;re including three other files for the ride. Add a few more levels of inclusion with header files including many other header files, and you have a recipe for disaster (or for really long build times at least).</p>
<p>As an experiment, I added one more feature to <a href="/wp-content/uploads/bin/analyze_includes.txt">the script I wrote last week</a>. The script analyzes a set of source code files and determines how many times each file is included by other files in a recursive way. So, in our trivial example above, file C will be reported as being included twice (once by B directly, and once by A indirectly). I then decided to test it on the source code for a high-level game library (I&rsquo;m not going to be any more specific since it wasn&rsquo;t particularly good code and it had a pretty hideous physical structure). I wouldn&rsquo;t be surprised if it&rsquo;s not very different from the level of complexity of a lot of game code out there. As a point of reference, the library was composed of 300 cpp files and 312 header files.</p>
<p>Before I ran the script, I tried to guess how many times the most included file in the whole library was included by other files. My guess was around 600 times, just because I knew that the physical structure of that code wasn&rsquo;t pretty. I figured maybe almost half the files included that one header file, and a few others included it indirectly. Boy was I wrong! Here are the shocking results:</p>
<table>
	<thead>
			<tr>
					<th>Top included files</th>
					<th></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>file1.h</td>
					<td>10777</td>
			</tr>
			<tr>
					<td>file2.h</td>
					<td>3683</td>
			</tr>
			<tr>
					<td>file3.h</td>
					<td>1438</td>
			</tr>
			<tr>
					<td>file4.h</td>
					<td>940</td>
			</tr>
			<tr>
					<td>file5.h</td>
					<td>859</td>
			</tr>
	</tbody>
</table>
<p>That means that during the course of a full build for those 300 cpp files, one header file could be included over 10,000 times! No wonder this particular library seemed to take a long time to compile. Notice that the other top files quickly drop to being included around 800 times each (which is still even higher than my initial estimate).</p>
<p>As a comparison, I tried running that same script on another, much smaller library, but also one with a much better physical structure and many fewer dependencies between files. This second library was only made up of 33 cpp files and 39 header files. The most included file was only included a total of 23 times (with the second one being included less than 10 times). So, having the number of classes grow by a factor of 10, caused the number of includes to grow by a factor of 1000. Clearly not a very scalable situation.</p>
<p>Things aren&rsquo;t quite that bad though. Header files typically have a set of include guards in them, to prevent the compiler from adding duplicate symbols if it encounters the same header file multiple times during the compilation of one cpp file. This is what include guards look like:</p>
<p>// SomeFile.h</p>
<p>#ifndef SOMEFILE_H_ #define SOMEFILE_H_</p>
<p>// Normal code goes here, even other #include statements if necessary</p>
<p>#endif</p>
<p>With every header file having include guards around it, I turned on the /showincludes switch in Visual C++ and performed a full build. The total number of includes during the course of building the 300 classes in the library was an astounding 15,264. Better than the worst-case-scenario we calculated earlier, but still tremendously high.</p>
<p>Apparently some C++ compilers try to optimize this situation by automatically caching header files and avoiding hitting the disk to reload them over and over. Unfortunately, there is very little hard data about that, and you&rsquo;re always at the mercy of your current compiler writer. Was that true for Visual Studio .NET 2003?</p>
<p><img alt="hourglass" loading="lazy" src="/physical-structure-and-c-part-2-build-times/images/hourglass_2.jpg"></p>
<h3 id="redundant-guards">Redundant Guards</h3>
<p>To test if I could speed up the compilation any, I added redundant include guards to the whole library. Redundant include guards are like the regular include guards, but they are placed around the actual #include statement. I first saw them mentioned in the book <a href="http://www.amazon.com/exec/obidos/ASIN/0201633620/ref=nosim/gamesfromwith-20">Large Scale C++ Software Design by John Lakos</a> (written in 1996), but popular wisdom claims that they are unnecessary with modern compilers. Well, time to test that.</p>
<p>This is what redundant include guards look like:</p>
<p>// Somefile.cpp</p>
<p>#ifndef SOMEFILE_H_ #include &ldquo;SomeFile.h&rdquo; #endif #ifndef SOMEOTHERFILE_H_ #include &ldquo;SomeOtherFile.h&rdquo; #endif</p>
<p>//&hellip;</p>
<p>I wrote <a href="/wp-content/uploads/bin/add_external_guards.txt">a quick script</a> to add redundant guards to all the source code and did a full build again. The number of includes reported by the compiler went down to 10,568 (from over 15,000). That means that there were about 5,000 redundant includes in a full build. However, the overall build time didn&rsquo;t change at all.</p>
<p><strong>Result</strong>: Zero. Apparently Visual Studio .NET 2003 (and probably most of the major compilers) does a pretty good job caching those includes by itself.</p>
<p><strong>Recommendation</strong>: Stay away from redundant include guards. I never liked having the including files know about the internal define, and if the guard ever changes it can easily break things. Besides, the code looks a lot messier and unreadable. It might have been worth it if we could define #include to expand to a redundant guard automatically, but I don&rsquo;t think that&rsquo;s possible with the standard C preprocessor.</p>
<h3 id="pragma-once">#pragma once</h3>
<p>Just in case, I decided to test another strategy and see if I obtained similar results. Instead of using redundant include guards, I added the #pragma once preprocessor directive to all header files. Visual C++ will treat files with that directive differently and it&rsquo;ll make sure that those files are only included once per compilation unit. In other words, it accomplishes the same thing as the external guards, just in a non-portable way. Here&rsquo;s <a href="/wp-content/uploads/bin/add_pragma_once.txt">another really simple script</a> to add #pragma once to all the header files.</p>
<p><strong>Result</strong>: No difference. Just as with redundant include guards, it seems that the compiler was smart enough already to optimize that case.</p>
<p><strong>Recommendation</strong>: Don&rsquo;t bother with it. It&rsquo;s a non-standard construct that doesn&rsquo;t get any apparent benefit. If you still feel compelled to use it, at least wrap it up with #ifdef checks for the correct version of Visual Studio.</p>
<h3 id="precompiled-headers">Precompiled Headers</h3>
<p>During a full build, every cpp file is treated as a separate compilation unit. For each of those files, all the necessary includes are pulled in, parsed, and compiled. If you look at all the includes during a full build, you&rsquo;re bound to find a lot of common headers that get included over and over for every compilation unit. Those are usually headers for other libraries that the code relies on, such as STL, boost, or even platform-specific headers like windows.h or DirectX headers. They are usually also particularly expensive headers to include because they tend to include many other header files in turn.</p>
<p>From our findings in the previous two sections, it is clear that some compilers cache the headers encountered for each compilation unit. However, they don&rsquo;t do anything about duplicated headers found across multiple cpp files, and that&rsquo;s where precompiled headers come in.</p>
<p>When using precompiled headers, we can flag a set of headers as being part of the precompiled set. The compiler will then process them all at once and save those results. Every compilation unit will then automatically include all the headers that were part of the precompiled set at the very beginning, but at a much lower cost than parsing them from scratch every time.</p>
<p>The catch is that if any of the contents of the precompiled headers changes, a full rebuild is necessary to compile the program again. This means that we should only add headers that are included very often throughout our project but that don&rsquo;t change frequently. Perfect candidates are the ones we mentioned earlier: STL headers, boost, and any other big external APIs. I always prefer not to include any headers from the project itself, although if you have a header that is included in every file, you might as well include it in the precompiled set (or, even better, change it so it&rsquo;s not included everywhere and improve the physical structure).</p>
<p>The gains from using precompiled headers are quite dramatic. The game library we mentioned in an earlier section took over 14 minutes to compile without pre-compiled headers, but only 2:30 when using them. Those are huge savings! Minimal rebuilds are also improved because we avoid parsing some of the common headers for one file, but the results aren&rsquo;t as dramatic as for full builds.</p>
<p>Precompiled headers are not without their downside though. The first problem is that precompiled headers often end up forcing the inclusions of more headers than it is absolutely necessary to compile each individual file. Not every file needs <vector> or &lt;windows.h&gt; included, but since a fair amount of them do and those are considered expensive includes, they&rsquo;ll invariably end up in the precompiled header section. That means that any compilation unit taking advantage of precompiled headers will be forced to include those as well. Logically, the program is the same, but we have worsened the physical structure of the source code. In effect, we are trading extra physical dependencies between files for a faster compile time.</p>
<p>The second problem is that precompiled headers are not something you can rely on from compiler to compiler and platform to platform. The only compilers I&rsquo;m aware of that implement them are <a href="http://msdn.microsoft.com/visualc/">Microsoft&rsquo;s Visual C++</a> and <a href="http://www.metrowerks.com/MW/Develop/CodeWarrior.htm">Metrowerks&rsquo; CodeWarrior</a> (although I just did a Google search and apparently <a href="http://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html">gcc also supports precompiled headers</a>--that&rsquo;s great news!). For the rest of us using different compilers, we&rsquo;re out of luck as far as this technique goes. Considering how important multi-platform development is becoming in the games industry (and elsewhere), this is a big blow against them.</p>
<p>Finally, by far the worst aspect of precompiled headers, is what happens when you combine the first two problems: Take a set of source code developed on a compiler where precompiled headers were available, and try to build it on a different platform. The code will compile since everything is standard C++, but it&rsquo;ll compile at a glacial pace. That&rsquo;s because every file is including a massive precompiled header file, and it is being parsed over and over for every compilation unit without taking advantage of any optimizations in the part of the compiler. If the code had been developed without precompiled headers in the first place, each file would only include those headers that it absolutely needs to compile, which would result in much faster compile times.</p>
<p>So earlier, when I said that the game library without precompiled headers took over 14 minutes to build, that&rsquo;s because it was written with precompiled headers in mind. Otherwise, I estimate it would only take about 5-6 minutes (still much longer than the 2:30 it took with precompiled headers).</p>
<p>Personally, I have never yet worked on a set of code that was developed to be compiled on multiple platforms and where some of them did not support precompiled headers. I suppose the best approach is to use #ifdefs to only include the precompiled headers in one platform and the minimal set of includes for the rest, but it seems like an extremely error-prone approach where programmers are going to be breaking the other platform&rsquo;s builds all the time. I&rsquo;d be interested to know how teams working in such an environment deal with it.</p>
<p><strong>Result</strong>: Huge gains both for full builds and minimal builds if your compiler supports them. Much worse physical structure.</p>
<p><strong>Recommendation</strong>: Definitely use them if you&rsquo;re only compiling in a platform that supports them. If you need to support multiple platforms, the gain is still too big to pass up. It probably is worth if you manage to separate the includes for precompiled headers with lots of #ifdefs and try to keep the physical structure sane for platforms that don&rsquo;t support them.</p>
<h3 id="single-compilation-unit">Single Compilation Unit</h3>
<p>This is an interesting trick that you won&rsquo;t find in most books. I first read about it in the <a href="http://lists.midnightryder.com/listinfo.cgi/sweng-gamedev-midnightryder.com">sweng-gamedev mailing list</a> about a couple of years ago. Be warned, this is hackish and ugly, but people claimed really good results. I just had to find out for myself how it stacked up against the other techniques to reduce build times.</p>
<p>This technique involves having a single cpp file (compilation unit) that includes all the other cpp files in the project (yes, that&rsquo;s right, cpp files, not header files). To compile the project we just compile that one cpp file and nothing else. The contents of this file are simply #include statements including all the cpp files we&rsquo;re interested in. Something along these lines:</p>
<p>// everything.cpp</p>
<p>#include &ldquo;MyFile1.cpp&rdquo; #include &ldquo;MyFile2.cpp&rdquo; #include &ldquo;MyFile3.cpp&rdquo; //&hellip;.</p>
<p>As you can imagine by now, I wrote <a href="/wp-content/uploads/bin/create_everything.txt">a script to create that file</a> from a directory containing the source code for a project. I just created a file including all the cpp files in that directory, although a better way of doing it would be to parse the make (or project) file and only include those files that are actually part of the project. That way, as I discovered, you avoid including outdated files or files that are in that directory but are not part of the project.</p>
<p>I created this file (everything.cpp), compiled it and&hellip; get ready: The build time went down from 2:32 minutes to 43 seconds! That&rsquo;s a 72% decrease in build time!! Not only that, but the .lib file it created from that library went from 42MB down to 15MB, so it should help with link times down the line. People in the mailing list reported even better results with gcc than with Visual Studio.</p>
<p>What is the reason for such reduction in build times? I can only speculate. I suspect part of it is due to avoiding the overhead of starting and stopping the compiler for every compilation unit. However, the biggest win probably comes from the reduced number of included files. Because everything is one compilation unit, we only include every file once. The second time any other file attempts to include a particular header file, the compiler will have already cached it (and it&rsquo;ll have include guards so there&rsquo;s no need to parse anything). To test this theory, I again turned on the /showincludes switch. Indeed, the number of includes during a full build went down from 10,568 to 3,197. That&rsquo;s a 70% reduction of included files, which is, probably not coincidentally, the same reduction in build time.</p>
<p>One very interesting observation from this experiment is that build times are probably more dependent on the number of actual includes performed by the compiler than I thought at first. All the more reason to keep a really watchful eye on the physical structure of the program. The third part of this article will cover what architectural choices we can make to improve the physical structure and keep the overall number of includes down.</p>
<p>Unfortunately this method also has its share of problems. One of the biggest problems is that there is no such a thing as a minimal build anymore. Any modification to any file will cause a full rebuild. Of course, the full build takes a only a fraction of the time it took before, so this might not be much of an issue.</p>
<p>As with precompiled headers, we&rsquo;re adding a lot of physical dependencies between files. In this case, files will have a physical dependency with any files that were included before it in the everything.cpp file.</p>
<p>However, the most objectionable of all problems is that we can now run into naming conflicts. Before we assumed each cpp file was a separate compilation unit. Now they&rsquo;ve all been forcefully added to the same one. Any static variables or functions, or anything on an anonymous namespace will be available to every cpp file that comes after it on the large everything.cpp file. This means that there&rsquo;s potential for having conflicting symbols, which is one of the things that anonymous namespaces were supposed to solve in the first place. If you have decided to use this technique, you will want to keep everything as part of a separate namespace or part of the class itself and avoid global-scope symbols completely.</p>
<p><strong>Result</strong>: Huge improvement in full-build times, but minimal-build times become much worse. Potential for clashing of static and anonymous namespace symbols.</p>
<p><strong>Recommendation</strong>: The gains of this technique are simply huge so it would be a shame to ignore it. It is probably no good for regular builds, but you might want to have it as an option when you just care about doing full builds (automated build machine or building someone else&rsquo;s code). If so, make sure to wrap symbols in namespaces or classes.</p>
<p><a href="/wp-content/uploads/bin/analyze_includes.txt"><img alt="icon" loading="lazy" src="/physical-structure-and-c-part-2-build-times/images/script.png"> analyze_includes.pl</a> <a href="/wp-content/uploads/bin/add_external_guards.txt"><img alt="icon" loading="lazy" src="/physical-structure-and-c-part-2-build-times/images/script.png"> add_external_guards.pl</a> <a href="/wp-content/uploads/bin/add_pragma_once.txt"><img alt="icon" loading="lazy" src="/physical-structure-and-c-part-2-build-times/images/script.png"> add_pragma_once.pl</a> <a href="/wp-content/uploads/bin/create_everything.txt"><img alt="icon" loading="lazy" src="/physical-structure-and-c-part-2-build-times/images/script.png"> create_everything.pl</a></p>
<p>The next (and final, I promise) part of this article will look at architectural choices that can greatly influence build times as well as looking briefly at link times and see what we can do about them.</p>]]></content:encoded></item><item><title>Physical Structure and C++ - Part 1: A First Look</title><link>https://gamesfromwithin.com/physical-structure-and-c-part-1-a-first-look/</link><pubDate>Fri, 05 Mar 2004 00:00:00 +0000</pubDate><guid>https://gamesfromwithin.com/physical-structure-and-c-part-1-a-first-look/</guid><description>&lt;p&gt;The physical structure of a C++ program is very important yet it is often overlooked. This two-part article will attempt to explain why the physical structure of a program is so important, present some useful guidelines, and show its effect on compile times.&lt;/p&gt;</description><content:encoded><![CDATA[<p>The physical structure of a C++ program is very important yet it is often overlooked. This two-part article will attempt to explain why the physical structure of a program is so important, present some useful guidelines, and show its effect on compile times.</p>
<p>A few days ago, Tom Whittaker (a friend who is currently working at <a href="http://www.firaxis.com/">Firaxis</a>) emailed me with some surprising facts about the behavior of the #include directive in the C++ compiler of Visual Studio .NET. It turns out that in <a href="http://www.amazon.com/exec/obidos/ASIN/1584502274/ref=nosim/gamesfromwith-20">my book</a>, I hinted that compilers often optimize the include step for header files and so they don&rsquo;t pay the costs of opening a file and loading it. When Tom turned on the /showincludes flag on the compiler, he saw that the same file was repeatedly being included by the compiler, even if it had internal include guards. He ran several interesting tests and I&rsquo;ll add a link from here whenever he gets around to putting them up on his web site (hint, hint, Tom).</p>
<p>All of that made me think again about the physical structure of a C++ program, how important it is, and how often it is overlooked. This two-part article will attempt to explain why the physical structure of a program is so important, present some useful guidelines, and show its effect on compile times.</p>
<h4 id="physical-structure">Physical Structure</h4>
<p>We are all familiar with the logical structure of a program. It deals with classes and functions and namespaces and templates. That&rsquo;s what you learn about in school, and what you read about in most C++ books. Design patterns, object oriented programming, etc, etc, all deal with the logical structure of a program. And, truth be said, it really is the most interesting part.</p>
<p>The physical structure of a program deals with the files that make up its source code. The .cpp and .h files, how they include each other, how they&rsquo;re subdivided into directories, etc. While not as interesting and sexy as the logical structure, it is crucial to understand the consequences of the physical layout of a program for any real-world project of any significant size. That includes just about every modern PC and console game, but probably not handheld devices because of their small code size.</p>
<p>Because it&rsquo;s not a particularly hot topic, not many books talk about the physical structure of a program. The best book in the subject is <a href="http://www.amazon.com/exec/obidos/ASIN/0201633620/ref=nosim/gamesfromwith-20">Large Scale C++ Software Design by John Lakos</a>. No technical lead should work on a game without at least having read parts of that book. Yes, some of the advice is a little outdated by today&rsquo;s standards (it&rsquo;s an almost antique book in the computer world&ndash;almost 10 years!), and some parts are a bit long winded with detailed measurements. Skip those in your first read and you&rsquo;ll still get a lot of gems along the way. Every time I come back to that book I end up getting something new out of it. I haven&rsquo;t read it in about 3-4 years, so it&rsquo;s just about due for another read.</p>
<p><img alt="tangle (c) freeimages.co.uk" loading="lazy" src="/physical-structure-and-c-part-1-a-first-look/images/tangle.jpg"> A good physical structure will result in files without many dependencies to other files, and with files clearly grouped in cohesive modules or libraries. On the other hand, a bad physical structure is one where files are related to other files from all over the project, without clear delimitations or boundaries. This is a clear example of the <a href="http://www.antipatterns.com/briefing/sld024.htm">&ldquo;blob&rdquo; antipattern</a>. Unfortunately, if left unchecked, this is the type of physical structure that develops over time.</p>
<h4 id="benefits-of-a-good-physical-structure">Benefits of a Good Physical Structure</h4>
<p>Why would anybody care about the physical structure? After all, the things we care about when we&rsquo;re writing a program are that it does what it&rsquo;s supposed to do, and that it does it fast. That might be true for a demo, or a throwaway project, but for a large project, maintainability is also a very important requirement. It&rsquo;s no good to have a very efficient class if we can&rsquo;t change it, and it&rsquo;s also no good if iteration to test a change takes a long time.</p>
<p>The benefits of a good physical structure of a program are:</p>
<ul>
<li>Better logical structure. Usually, keeping an eye on the physical structure of a program results in a better logical structure. By reducing the dependencies between files, we will probably reduce dependencies between classes. It is often the case that unexpected connections will grow between classes and even different libraries if their header files are already included. Programmers won&rsquo;t have anything to remind them that they&rsquo;re just adding a new dependency when they decide to call some global function.One of my pet-peeves when programming for Windows is having windows.h included in every single .cpp file, either directly or indirectly. In the type of programs I write, most classes don&rsquo;t need anything in windows.h, yet it is forced down their throats. At one point I attempted to remove a global windows.h include in a library since it was supposedly not needed anywhere, just to have to give up because of the many unnecessary DWORD, BOOL, and screwed up min and max calls scattered everywhere on the source code.</li>
<li>Easier to refactor. If you think of each file as a little box literally connected with a string to all the other files it depends or is dependent on, the more of those strings there are, the harder it is to untangle it from the overall mess and separate it. It is the same thing with refactoring: The worse the physical structure, the harder it is to make any refactoring changes that involve separating or isolating sections (which, in my experience, it&rsquo;s one of the most crucial refactorings you have to do to prevent programs from growing into the â€œblobâ€ antipattern).</li>
<li>Easier to test. Not surprisingly, the more modular and independent the project is, the easier it becomes to write unit tests for it since each piece can be tested separately from the rest. Unit tests really benefit from having very few dependencies, so one of the many benefits reaped by doing test-first development is a very modular design with a logical and physical structure that has very few dependencies.</li>
<li>Faster compile times. This might come as a surprise to some people, but it is usually the most tangible and objective result of having a good (or bad!) physical structure. Usually, the worse the physical structure, the longer the compile times will be. Compile times are an issue for large projects. Even with the fastest machines today, full builds on large projects can easily take hours. More importantly, builds caused by changing just a file or two can trigger builds that last almost that long. Needless to say, having such a delay every time a change is made is not exactly encouraging programmers to test their work and iterate it to make it better. Part two of this article will look exclusively at compile times.</li>
</ul>
<h4 id="guidelines">Guidelines</h4>
<p>Here&rsquo;s a distilled set of guidelines from Lakos&rsquo; book that minimize the number of physical dependencies between files. I&rsquo;ve been using them for years and I&rsquo;ve always been really happy with the results.</p>
<ol>
<li>Every cpp file includes its own header file first. This is the most important guideline; everything else follows from here. The only exception to this rule are precompiled header includes in Visual Studio; those always have to be the first include in the file. More about precompiled headers in part two of this article.</li>
<li>A header file must include all the header files necessary to parse it. This goes hand in hand with the first guideline. I know some people try to never include header files within header files claiming efficiency or something along those lines. However, if a file must be included before a header file can be parsed, it has to be included somewhere. The advantage of including it directly in the header file is that we can always decide to pull in a header file we&rsquo;re interested in and we&rsquo;re guaranteed that it&rsquo;ll work as is. We don&rsquo;t have to play the &ldquo;guess what other headers you need&rdquo; game.</li>
<li>A header file should have the bare minimum number of header files necessary to parse it. The previous rule said you should have all the includes you need in a header file. This rule says you shouldn&rsquo;t have any more than you have to. Clearly, start by removing (or not adding in the first place) useless include statements. Then, use as many forward declarations as you can instead of includes. If all you have are references or pointers to a class, you don&rsquo;t need to include that class&rsquo; header file; a forward reference will do nicely and much more efficiently.</li>
</ol>
<p>One unfortunate aspect of those guidelines is that the compiler doesn&rsquo;t really care one way or another. As long as you provide enough includes, the compiler will happily churn away at the source code and come up with the desired object file. It is up to us to minimize the number of includes and to follow those rules. While it seems fairly straightforward at first (after all, it is only three rules), things get more complicated as soon as heavy refactoring starts. As you split classes, move functions, and consolidate functionality, there might be several unnecessary headers. The only quick way to verify whether they&rsquo;re needed or not is to, gulp, comment them out and try to compile the file.</p>
<p>This situation is more common in large files, which are the ones you&rsquo;re most likely going to be refactoring. If left unchecked, you&rsquo;ll soon be left with a myriad little tendrils connecting your file to the rest of the code without getting any benefit from it. Wouldn&rsquo;t it be great if there was an automated tool that would check that?</p>
<h4 id="automating-the-guidelines">Automating the Guidelines</h4>
<p>I did a quick search and I couldn&rsquo;t find any tools or scripts that did exactly what I wanted. I suppose that a massive C/C++ style-checker tool might look for some of those things (like redundant includes), but nothing jumped out. Most programs are more concerned with checking logical errors and constructs than looking at the physical structure. I started from <a href="http://www.aristeia.com/ddjpaper1_frames.html">Scott Meyers&rsquo; summary of major C++ checkers</a>. In particular I looked at <a href="http://www.abxsoft.com/codchk.htm">CodeCheck</a>, <a href="http://www.gimpel.com/html/lintinfo.htm">PC-Lint</a>, and <a href="http://www.parasoft.com/jsp/products/home.jsp?product=Wizard&amp;">CodeWizard</a>. I admit that I didn&rsquo;t look too deep into them, so maybe they also check for some of these guidelines, but it&rsquo;s certainly not their biggest selling point from reading their web sites.</p>
<p>As a quick challenge, I decided to try and write a quick script to check against those guidelines. Soon I realized that you can&rsquo;t really have the word &ldquo;quick&rdquo; in anything related to parsing C++. I was quickly reminded how ugly the language is, how many quirks it has, how much baggage it a carries around. Java looks mighty tempting sometimes.</p>
<p>I decided that if I was going to have a chance to do this, I would need to leverage other software to parse the source code for me and the script could work directly on the abstract representation of the program. Not exactly what I had in mind, but I stumbled on the XML and perlmod output generated by <a href="http://www.doxygen.org/">Doxygen</a>. I have been using Doxygen for years, but I always thought of it as a pretty documentation generator. I never realized what a powerful and robust C++ parser it was until now.</p>
<p>In a few hours I was able to put together a <a href="/wp-content/uploads/bin/analyze_includes.txt">quick Perl script</a> that hooks up to the <a href="http://www.stack.nl/~dimitri/doxygen/perlmod.html">perlmod</a> output of Doxygen that checked against those rules. Guideline #1 was the easiest one to check against. Really, you don&rsquo;t even need a fancy parser for that. Guideline #2 is already checked by the compiler (if you don&rsquo;t have enough includes, the program won&rsquo;t compile). Guideline #3 is the trickiest one. Still, the script makes a valiant effort and checks for the most common cases. It&rsquo;ll try to detect whether an include is not needed at all, or whether it can be replaced with a forward declaration.</p>
<p>However, the script is a conservative one and will not always detect that a header is necessary. It deals fine with simple constructs such as member variables, enums, references, and pointers. However it seems that Doxygen has very little knowledge of preprocessor directives, so it won&rsquo;t catch any #defines brought in from header files. Doxygen also seems very limited in how it deals with inline functions (probably because Doxygen is looking mostly at the logical rather than the physical structure of the program). It would probably be possible to deal with templates, but I didn&rsquo;t bother making it that far. The script also detects duplicate includes, both in header files and cpp files.</p>
<p>Even with all those limitations, the script can easily deal with about 80% of the cases in most of the code I work with on a regular basis. It was certainly insightful running it on the source code for some of the libraries I work with. I saw plenty of instances where headers could in fact be removed and the physical structure of the program improved. I would love to see a robust tool along these lines that could be ran quickly enough after each compile, or at least once a night in our automated build machine.</p>
<p><img alt="icon" loading="lazy" src="/physical-structure-and-c-part-1-a-first-look/images/script.png"> <a href="/wp-content/uploads/bin/analyze_includes.txt">analyze_includes.pl</a></p>
<p><a href="/?p=8%20">Part two of this article</a> will look at the consequences of physical structure on compile times, and what we can do to improve that.</p>]]></content:encoded></item></channel></rss>