January 04, 2005
Improving code turnaround time
There is a major problem with applying these techniques to games development. Build times for most games these days is anything but fast. A build time of 3 minutes would be quite fast, even for a code change that affects a small number of source files. See Noel Llopis's articles on C++ physical structures for some tips on improving the build times of C++ programs.
Unfortunately, even using all of the techniques he describes, I don't think I will be able to get build times as fast as I would like so I can write games the way I really want to. To program efficiently, it will be necessary to make more than one code change step per build / test iteration, as I have to do now on my current game project.
As I see it, the problem is quite fundamental to C++. From C it inherits the use of header files and a separate linking step in order to achieve source-file level modularity and incremental builds. This approach simply does not scale well to current games projects. As games platforms have increased in power, the games we write for them have increased in size. Although the power of the computers we use to build them has also increased, every year we see build times get longer and longer.
If you have read any of my previous posts, you will probably not be surprised that I introduce C# at this point. C#, unlike its ancestors C and C++, does not use header files or a separate link step. And this pays off. It's build times are orders of magnitude shorter. As an experiment, I built a mid-sized C# program, probably about the same size as a typical game these days, 8MB of source code in total. A full rebuild took 38 seconds. A dependency check, with no files modified took 3 seconds. These are the kinds of build times I need to apply refactoring effectively.
I am writing a C# to C++ translator. My idea is to translate C# into C++ and then use a C++ compiler and linker to generate native code for a games platform. Although I think I can generate the C++ code in such a way as to reduce build times, for example by minimizing header dependencies and using forward declaration wherever possible, it will still take significantly longer than C# compilation.
But I've had another idea. Although I need to compile to native code in order to run on a games platform such as a console, I can run the C# program, prior to translation to C++, on any platform with a .NET virtual machine, e.g. a Windows PC. So my idea is to perform several programming iterations only building and testing for a .NET target platform. Having performed several iterations, I will build for my actual games platforms and test on those, ideally using a build farm that will automatically build, deploy and test for me, while I get on with the next batch of iterations. I think this could work very well for the majority of code, which is not tied to features specific to a particular games platform.
Obviously, even if C# is used in a games project, a lot of code will still need to be written in a language like C++, I would estimate up to 50%, depending on the project and the platforms. This code will not run on a .NET virtual machine. Fortunately the .NET framework offers many ways to allow "managed" code to link with "unmanaged" code like C++. In Microsoft's implementation, this might be done using Managed C++. So the C++ game code might be compiled to a Windows DLL that would be loaded by the .NET virtual machine and linked with the C# code being tested.
One of the most pleasant programming experiences in the last few years is when I was working on some subsystems using TDD (Test-Driven Development). I had it set up so I only liked against the minimum number of libraries necessary (as opposed to pulling the whole game engine). I also had it set up so my test project was dependent on the library I was working on, and, as a post-build step, it executed itself to run the tests.
I was able to make a change to a single cpp file, initiate a build, and see the results of the tests in less then 4-5 seconds. With a setup like that, it was really like being in heaven. My fingers would twich over to F7 every so often, even if I hadn't changed any code and I was just talking to someone :-)
If you're working on much higher level code (and at that point, it's worth asking if it has to be done in C++), it's also possible to achieve great iteration times by using DLLs (which would have to be replaced with static libraries or some sort of overlays on console platforms that don't support them).
There's always "edit and continue" if you're using Visual Studio, but I've only had bad experiences with it, even though I know some people who swear by it. To me it feels just as broken as incremental linking (which stops working as soon as you modify a library--which is where 99.99% of my code always is).
From the principles of the Agile Manifesto:
"Simplicity - the art of maximizing the amount of work not done - is essential"
After the experiences at Argonaut I was convinced there was a better way of keeping track of these things and set out to make tools to help coders in their day-to-day lives. One of those tools is IncludeManager - a Visual Studio Add-in that shows your header file dependencies and interactively updates while you edit your code. Bottlenecks are made really clear when you have a full dependency graph! There's a 14 day trial available from our web-site.
Keeping the build times down is difficult, but it is achievable, and having a code time turnaround in seconds instead of minutes revitalises coders' enthusiasm and makes tweaking code a pleasure and not a chore - the kinds of changes you make in games where that last tweak can make the difference between an 'ok' game and award-winning game-play!
Your blog is awesome, nice, informative and very interesting for our visitors. I hope our services will be helpful for your visitors. Our services include good, quality professional web design services, psd to html conversion,Psd to html slicing, Psd to wordpress, ecommerce website development, seo, data entry,windows mobile apps, web research.