Tuesday, August 31, 2010

Tundra, my build system

I've been working on a build system, Tundra, to scratch my own itches and it's come along far enough that I've released the code in beta form over at github (http://github.com/deplinenoise/tundra).

Tundra has taken on many different architectures over the years I've hacked on it, but I've finally arrived at a Lua frontend and a C backend. Here are some of the goals I've had with Tundra:

  • Optimize for iterative builds
  • Flexible configuration frontend (easy to add configurations and variants)
  • Keep the build system core small and simple
  • Utilize multi-core hardware even for scanning and up-to-date checks
  • Reliably support code generation (passes, DAG scheduling)
  • Separate configuration and building to make it easier to optimize & debug

Of course now that Tundra is nearing completion it's fun to show some performance numbers. Noel Llopis did a great writeup on the various build systems available a few years back (http://gamesfromwithin.com/the-quest-for-the-perfect-build-system). Using his script to generate 10 libraries with 50 files each (500 files total) I ran a small benchmark. Here's the statistics output from a no-act run of Tundra on that dataset. This was on a Core i7 box running Win7/64 with everything in disk cache; but the disk itself is a slow 7200 RPM disk:

J:\Scratch\benchmark>tundra --debug-stats
*** build success, 0 jobs run
post-build stats:
  files tracked: 1511 (1511 directly from DAG), file table load 1.64%
  relations tracked: 1034, table load 1.12%
  relation cache load: 0.003s save: 0.000s
  nodes with ancestry: 513 of 513 possible
  time spent in Lua doing setup: 0.057s
    - time spent iterating directories (glob): 0.004s over 10 calls
  total time spent in build loop: 0.032s
    - implicit dependency scanning: 0.152s
    - output directory creation/mgmt: 0.000s
    - command execution: 0.000s
    - (parallel) stat() time: 0.039s (2010 calls out of 0 queries)
    - (parallel) file signing time: 0.031s (md5: 0, timestamp: 1500)
    - up2date checks time: 0.016s
  efficiency: 0.00%
total time spent in tundra: 0.0926s

I'd say 93 ms for a no-act build is pretty nice considering that this includes full #include scanning! We can see that 57 ms was spent in Lua code creating the input DAG and 32 ms was spent in the native build loop. This is nice because if the build master is complaining about slow builds we can easily see if it's due to his bad scripting or due to actual build performance ;)

If you want to give Tundra a spin (it's beta quality software) you can get a binary drop and the documentation here: http://github.com/deplinenoise/tundra/downloads.