Why Use Clang?
Clang is a compiler front-end for C, C++, Objective-C and (now) Objective-C++. It's built on top of the Low Level Virtual Machine (LLVM), the project that aims to provide a modern compiler infrastructure, that projects (like Clang) can be built upon. Like LLVM, Clang aims to provide a modern front-end compiler for the aforementioned languages and is seen to be the eventual drop-in replacement for GCC.
So enough about what Clang is, why bother using it when GCC is so widely supported, as well as some might argue, nothing actually wrong with it. If it ain't broke don't fix it, right? Ok, so I'm not going to go into any great detail about why GCC is so flawed and Clang isn't (because no software is perfect, not even compilers), mainly because I don't know enough about either project to do so and I'm not going to start pretending like I do. I am however going to point out some benefits of Clang and why you should consider looking into it.
The development of Clang is actively sponsored by Apple and although it's not currently (though it should be within the near future) the default compiler (GCC 4.2.1 is) when installing the developer tools, it is included in the form of Clang 1.5. If your project hasn't got a huge dependency on GCC, then I'd definitely recommend giving Clang a try and checking out firsthand the benefits over GCC that it can provide. Since it's designed to be compatible with GCC as much as possible, it's usually as simple as selecting it as the compiler within your Xcode project or a target's build settings.
The most obvious benefit of using Clang is performance. Performance is said to be one of the key aims of the project, in the sense of performing significantly faster at compile time as well as subsequently producing more efficient binaries than GCC, all the while using significantly less memory in the process. Check out the performance section of Clang's Features and Goals page as well as the dedicated performance page for specific in-depth details and stats on how it performs compared to GCC. I say that performance is the most obvious benefit to using Clang, because it really is that noticeable once you start using it. For example, we switched to building Sequel Pro using Clang a while ago, and the performance benefits during builds were immediate:
real 4m13.692s user 6m14.724s sys 0m57.559s
real 2m18.764s user 3m11.980s sys 0m32.187s
The above times were obtained from executing the following command, which builds a release build1 of Sequel Pro, including all it's dependencies:
time xcodebuild -project sequel-pro.xcodeproj -configuration Release build
There are a lot of factors to consider when profiling the performance of a particular process, the most obvious being the hardware it's running on2 and the current utilisation of the CPU, memory and other system resources during the build and the list goes on, but being almost twice as fast when performing a clean build is nonetheless impressive. It's also pretty obvious, but the above times are for building the entire application, not just compiling the Objective-C source files. This means it includes the copying of resources (images, templates, preference
plists, etc) and frameworks as well as compiling NIB/XIB files using
ibtool. That is, the general process of packaging all of the resources and binaries that results in a usable application. Clang's performance page refers to this time as non-compiler, an overhead of the build system (i.e.
xcodebuild). You generally won't see such a big performance hit when compiling a pure C command line program. It also goes without saying that you're not going to be performing a clean release build every time you change a source file during development, which is where (if you're on a Mac that is) Xcode's or
xcodebuild's (which are essentially the same thing) incremental compilation kicks in, so you might not see huge speed improvements every time, but it is definitely faster and less memory intensive.
Sequel Pro isn't exactly a massive project. It isn't small, but it has a relatively simple source tree and only 5 dependencies, all of which are included in it's trunk. According to Xcode Statistician Sequel Pro's source contains nearly 68,000 SLOC, excluding the source to all it's dependent frameworks that we build ourselves. It's therefore only fair that Clang be tested against another much larger project, for example, Adium, which by my estimate contains roughly 150,000 SLOC. I chose Adium, because (1) my basic estimates show it's more than twice the size of Sequel Pro (and in actuality is probably much larger) and (2) because it's an OS X application it also incurs the same non-compiler overhead associated with building the entire application and not just compiling it's source. The results were not surprising:
real 11m53.566s user 15m9.794s sys 4m32.265s
real 7m44.828s user 9m3.748s sys 2m45.088s
Note that all of the above timed builds were done for release configurations3 of the respective applications and although they'll defer in some very slight ways the process is generally the same. The point is, performing a release and development (or debug) build of the same application is a very different process and release configurations were simply chosen in this case to put both compilers through their paces with respect to these differences. The main difference should be obvious, the target architectures that the resulting application should be able to run on are different. During development, it's generally expected that the built application is only going to be used by the developer and so there's not much point in building it for any other architecture4 other than the architecture of the developer's system. A release build on the other hand is intended to be distributed to your users and so should be built for whatever architectures you intend to support.
The above stats might show Clang out performing GCC, but both versions of the compilers are not exactly up to date. GCC 4.2.1 was released back in July 2007 and although I don't have a specific release date for Clang 1.5, version one was released along with LLVM 2.6 in October 2009, so it's safe to assume it's less than a year old. It therefore might be unfair to compare these versions considering Clang has potentially well over two years of development time over GCC, but they're both the default versions included with Apple's developer tools. In some ways it could explain some of the large differences seen in compilation times between the two compilers, but I'm not convinced it can explain them all. Having said this I could be wrong.
Finally, having established the relative age of both compiler versions I was interested in seeing how their latest and greatest versions would perform. I originally intended to use the most up to date release versions of both compilers, that being GCC 4.4.5 and Clang 2.8, both released this month on the 1st and 5th respectively, but that didn't exactly go to plan. Having spent hours trying to get GCC to compile cleanly I gave up, so this isn't as much as a comparison of the latest versions of GCC and Clang, but more of a this is how the latest version of Clang compares to version 1.5. In contrast to GCC, building LLVM/Clang was super easy, but it did take a bit of tweaking to get Xcode to use it properly, but I'll spare the details for another post. The following times are also from using a trunk build of LLVM/Clang, which is labelled as version 2.9 (i.e. the next stable release):
real 1m40.509s user 2m34.364s sys 0m17.281s
real 7m52.085s user 10m14.829s sys 2m18.600s
As the times indicate, the results are varied. Sequel Pro builds quite a bit faster (~40 seconds), but building Adium is actually slightly slower. As I already mentioned there are a lot of factors to consider when profiling performance, especially time so I'd keep these in mind when comparing the numbers.
Finally, a performance analysis wouldn't be complete without some colourful graphs or charts illustrating the data. The following charts therefore show all of the above builds split out by compiler (note that times are in minutes and shorter bars are better):
The above times include all of the output from the
time command, and while interesting to see the user and system CPU time spent involved in executing the commands5, from a user's perspective the real time is the one that matters. That is, it indicates the actual real world elapsed time that it took for the command to complete.
So if you've read this far, then in short I think Clang is really awesome and think you should too. I've only presented one of the main benefits of it over GCC here and I'm not suggesting you should ditch GCC simply because of it, but rather you try it out and decide for yourself. Clang is not quite fully GCC compatible, but it also has a lot to offer that GCC doesn't that I haven't already mentioned. For example, it provides much more informative (and less cryptic) warning and error messages (diagnostics), much better IDE integration and a very impressive static analyzer to help track down bugs, specifically potential memory leaks in your applications.
Update: Something I failed to notice during my tests is that Clang 1.5 does not support compiling for the PPC (PowerPC) architecture. Attempting to do so produces the following warning:
clang: warning: not using the clang compiler for the 'powerpc' architecture, at which point it will fallback to using GCC. You can see this by passing the
-### option to see the commands that it would execute during compilation. The fact that the PPC architecture isn't fully supported is actually mentioned in the Clang manual where it states that some support is included, but significant pieces are still missing. I guess PPC support either didn't exist or wasn't enabled in Clang 1.5. This warning however is not present when using version built from trunk (2.9) and using the
-### option shows that Clang is at least used to generate the assembly, but it still falls back to GCC for machine code generation. This small difference could potentially explain some of the performance improvement that Clang 2.9 has over 1.5.
- A release build of Sequel Pro is built for 32/64-bit i386 (Intel) and 32-bit PPC (PowerPC) architectures. ↩
- In this case the hardware used was a 2006 MacBook Pro with a 2 GHz Core Duo Yonah processor, 2GB RAM and 320GB 5400RPM drive. I'd be interested to see how well both GCC and Clang take advantage of huge amounts of parallelism and memory available in current hardware, for example, an 8 or 12-Core Mac Pro.↩
- Both Sequel Pro and Adium's trunk source were used when building both applications, not their most recent stable release. Also, unlike Adium's current stable release, which is built as a 32-bit universal binary (32-bit i386/PPC), it's trunk (which is intended for all versions beyond 1.4) is built for the same architectures as Sequel Pro (32/64-bit i386, 32-bit PPC). ↩
- You could argue the case for building an application for other architectures other than for the system that it's being run on during development or debugging if you're actually testing or debugging architecture specific features and issues. ↩
- Looking into the user and system CPU time spent during the build process should give you a good idea of what the compilers spend the majority of their time doing in terms of internal processes and system calls. ↩