Compilation speedup suggestion

Hello Juce team,

We build quite a few JUCE targets regularly on CI. As an optimisation we’re using ccache, which caches object files, meaning that translation units which haven’t changed can just be downloaded rather than rebuilt.

I was looking at a build trace of the CI runs the other day and I noticed that juce_core.cpp (or juce_core.mm) is taking up a large proportion of our build time. It seems it’s being rebuilt every time despite ccache.

Hunting around I found that juce::Time::getCompilationDate() uses the __DATE__ and __TIME__ macros, which mean that all of juce_core must be rebuilt, whether it’s changed or not. I suspect this is why it’s dominating our CI time in cases where most other object files are cached.

We don’t actually use this function, so I’m wondering about ways to “not pay for what we’re not using”.

There is a ccache configuration option which allows you to ‘ignore’ those macros when hashing a file, which could be an option. But then if somebody uses them in future they’re likely to end up with silently incorrect builds.

The most ‘blunt’ approach might be to just add a macro define that excludes this function from juce::Time. It’s low effort, and builds will fail if someone tries to use the function. But of course it’s not the prettiest.

Another option would be for JUCE to make a separate translation unit alongside juce_core.cpp whose only purpose is to compile __DATE__ and __TIME__. This tiny TU would rebuild on every CI run, but it should be very fast. Of course you’d also need a header which could be just included by juce_Time.cpp or exposed publicly.

Do you have any thoughts on the matter?

11 Likes

I second this, adding a juce_core_compiledate.cpp file in the juce_core module including just the function bodies which contains those macros could be an easy win.

1 Like

Yep, adding an additional cpp file sounds like the perfect solution. Wouldn’t be a public change either, as you can just move the implementations from Time.cpp into the new file.

Yep, adding an additional cpp file sounds like the perfect solution. Wouldn’t be a public change either, as you can just move the implementations from Time.cpp into the new file.

Yes, that can work. Although I did an experiment and found that this is the most efficient way:

//=========================================
// juce_core/time/juce_CompilationTime.h
namespace juce
{
const char* getCompilationDateString();
const char* getCompilationTimeString();
}

//=========================================
// juce_core_compilation_time.cpp
#include "time/juce_CompilationTime.h"

namespace juce
{
const char* getCompilationDateString() { return __DATE__; }
const char* getCompilationTimeString() { return __TIME__; }
}

//=========================================
// juce_core.h
#include "time/juce_CompilationTime.h"

Then use these instead of __DATE__ and __TIME__ in juce_Time.cpp. This way the new translation unit doesn’t need to include juce_core.h to get String, StringArray, and all their dependencies.

This won’t actually help, because each juce module is compiled as one large translation unit anyway…

But that’s only because of the manual inclusion of every .cpp in the module into juce_core.cpp. If you just don’t include this new stuff in juce_core.cpp and put it in its own cpp instead, you’ve divided the module into two translation units.

1 Like

Exactly, i use this ability to divide frequently used parts from seldom used ones in my modules

1 Like

Sure, but this would require special handling in the juce build system (Projucer & cmake) to set up the multiple translation units for juce core specially…

It wouldn’t actually.

You can add files like juce_core_time.cpp to add TUs and that feature is already supported in the current build system in both Projucer and CMake, I use it sometimes when wrapping external libs in a module.

You can see an example for this in juce_audio_plugin_client that compiles a few TUs in the same module (for AAX, VST3, etc).

1 Like

Oh nice, I didn’t realize that was part of the juce module spec

I think this is a good idea. The whole team is busy preparing JUCE 8 at the moment, but we’ll look at doing something along these lines shortly afterwards.

6 Likes