While working on some D REPL improvements I found the turnaround times for recompiling the project somewhat annoying. It only takes a few seconds, but when tweaking the style of a page every second between saving a change and seeing the result is too much. This is also a bit surprising as D REPL is just a very small vibe.d app with only a single page template.
So let’s try to find out what is taking so long by profiling a basic vibe.d app.
dub init vibed-turnaround vibe.d
cd vibed-turnaround
dub build
Now “change” something and rebuild app.
touch source/app.d
time dub build
That prints 4.4s on my machine, something around 1s would be nice to work with. Let’s get some more detailed numers. Rebuilding the vibe.d project basically consists of 3 steps, running dub to check dependencies, compiling the project and linking the final binary. We’ll get the commands for each step by running dub in verbose mode
touch source/app.d
dub build -v
and then measure the minima of 10 runs using avgtime.
# dub time (cached build)
avgtime -r 10 dub build
# compile time
avgtime -r 10 dmd -c -of.dub/build/application-debug-linux.posix-x86_64-dmd_2065-84BE4C49CAEF5E71588D56CC0DC1CAB2/vibed-turnaround.o -debug -g -w -version=VibeDefaultMain -version=VibeLibeventDriver -version=Have_vibed_turnaround -version=Have_vibe_d -version=Have_libevent -version=Have_openssl -Isource/ -I../../../.dub/packages/vibe-d-0.7.20/source/ -I../../../.dub/packages/libevent-master -I../../../.dub/packages/openssl-master -Jviews source/app.d ../../../.dub/packages/vibe-d-0.7.20/source/vibe/appmain.d
# link time
avgtime -r 10 dmd -of.dub/build/application-debug-linux.posix-x86_64-dmd_2065-84BE4C49CAEF5E71588D56CC0DC1CAB2/vibed-turnaround .dub/build/application-debug-linux.posix-x86_64-dmd_2065-84BE4C49CAEF5E71588D56CC0DC1CAB2/vibed-turnaround.o ../../../.dub/packages/vibe-d-0.7.20/libvibe-d.a -L--no-as-needed -L-levent_pthreads -L-levent -L-lssl -L-lcrypto -g
So linking takes most of the time. One reason is that dmd still uses static linking by default, therefor the linker has to find and copy all required symbol out of archive files into the resulting binary, the basic vibe.d app is 5MiB (18MiB with debug info). Using dynamic linking drastically reduces the required link time (0.62s instead of 2.74s) because the symbols can be looked up in a compact table and must not be copied. Shared libraries are still a bit cumbersome to use with dub though.
Another possibility to speed up linking is to use the much faster¹ gold linker (ld.gold) instead of the default ld.bfd.
This is how you can switch the linker on certain platforms.
Fedora/CentOS
sudo alternatives --set ld /usr/bin/ld.gold
# to use ld.bfd again
sudo alternatives --set ld /usr/bin/ld.bfd
Debian/Ubuntu
update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.gold" 20
update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.bfd" 10
# manually select linker
update-alternatives --config ld
FreeBSD
pkg install binutils
mv /usr/bin/ld /usr/bin/ld.orig
ln -s /usr/local/bin/ld.gold /usr/bin/ld
# to use ld.bfd again
ln -sf /usr/local/bin/ld.bfd /usr/bin/ld
With gold it only takes 0.47s for static and 0.16s for dynamic linking. So static linking with gold is even faster than dynamic linking with ld.bfd.
In the next part we’ll speed up the compilation step.