<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Blog blog("Baptiste Wicht"); (Posts about time)</title><link>https://baptiste-wicht.com/</link><description></description><atom:link href="https://baptiste-wicht.com/categories/time.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Sun, 15 Feb 2026 06:57:39 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Blazing fast unit test compilation with doctest 1.1</title><link>https://baptiste-wicht.com/posts/2016/09/blazing-fast-unit-test-compilation-with-doctest-11.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;p&gt;You may remember &lt;a class="reference external" href="http://baptiste-wicht.com/posts/2016/06/reduce-compilation-time-by-another-16-with-catch.html"&gt;my quest for faster compilation times&lt;/a&gt;. I had made several changes to the Catch test framework macros in order to save some compilation at the expense of my test code looking a bit less nice:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code cpp"&gt;&lt;a id="rest_code_99207774a09f4a598386048725bcc49e-1" name="rest_code_99207774a09f4a598386048725bcc49e-1" href="https://baptiste-wicht.com/posts/2016/09/blazing-fast-unit-test-compilation-with-doctest-11.html#rest_code_99207774a09f4a598386048725bcc49e-1"&gt;&lt;/a&gt;&lt;span class="n"&gt;REQUIRE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//Before&lt;/span&gt;
&lt;a id="rest_code_99207774a09f4a598386048725bcc49e-2" name="rest_code_99207774a09f4a598386048725bcc49e-2" href="https://baptiste-wicht.com/posts/2016/09/blazing-fast-unit-test-compilation-with-doctest-11.html#rest_code_99207774a09f4a598386048725bcc49e-2"&gt;&lt;/a&gt;&lt;span class="n"&gt;REQUIRE_EQUALS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//After&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first line is a little bit better, but using several optimizations, I was
able to dramatically change the compilation time of the test cases of ETL. In
the end, I don't think that the difference between the two lines justifies the
high overhead in compilation times.&lt;/p&gt;
&lt;section id="doctest"&gt;
&lt;h2&gt;doctest&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/onqtam/doctest"&gt;doctest&lt;/a&gt; is a framework quite similar to
Catch but that claims to be much lighter. I tested doctest 1.0 early on, but at
this point it was actually slower than Catch and especially slower than my
versions of the macro.&lt;/p&gt;
&lt;p&gt;Today, doctest 1.1 was released with promises of being even lighter than before
and providing several new ways of speeding up compilation. If you want the
results directly, you can take a look at the next section.&lt;/p&gt;
&lt;p&gt;First of all, this new version improved the basic macros to make expression
decomposition faster. When you use the standard REQUIRE macro, the expression is
composed by using several template techniques and operator overloading. This is
really slow to compile. By removing the need for this decomposition, the fast
Catch macros are much faster to compile.&lt;/p&gt;
&lt;p&gt;Moreover, doctest 1.1 also introduces CHECK_EQ that does not any expression
decomposition. This is close to what I did in my macros expect that it is
directly integrated into the framework and preserves all its features. It is
also possible to bypass the expression checking code by using FAST_CHECK_EQ
macro. In that case, the exceptions are not captured. Finally, a new
configuration option is introduced (DOCTEST_CONFIG_SUPER_FAST_ASSERTS) that
removes some features related to automatic debugger breaks. Since I don't use
the debugger features and I don't need to capture exception everywhere (it's
sufficient for me that the test fails completely if an exception is thrown), I'm
more than eager to use these new features.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="results"&gt;
&lt;h2&gt;Results&lt;/h2&gt;
&lt;p&gt;For evaluation, I have compiled the complete test suite of ETL, with 1 thread,
using gcc 4.9.3 with various different options, starting from Catch to doctest
1.1 with all compilation time features. Here are the results, in seconds:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th class="head"&gt;&lt;p&gt;Version&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Time&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;VS Catch&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;VS Fast Catch&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;VS doctest 1.0&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;Catch&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;724.22&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;Fast Catch&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;464.52&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;-36%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;doctest 1.0&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;871.54&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;+20%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;+87%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;doctest 1.1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;614.67&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;-16%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;+32%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;-30%&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;REQUIRE_EQ&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;493.97&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;-32%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;+6%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;-43%&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;FAST_REQUIRE_EQ&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;439.09&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;-39%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;-6%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;-50%&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;p&gt;SUPER_FAST_ASSERTS&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;411.11&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;-43%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;-12%&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;-53%&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;As you can see, doctest 1.1 is much faster to compile than doctest 1.0! This is
really great news. Moreover, it is already 16% faster than Catch. When all the
features are used, doctest is 12% faster than my stripped down versions of Catch
macros (and 43% faster than Catch standard macros). This is really cool! It
means that I don't have to do any change in the code (no need to strip macros
myself) and I can gain a lot of compilation time compared to the bare Catch
framework.&lt;/p&gt;
&lt;p&gt;I really think the author of doctest did a great job with the new version.
Although this was not of as much interest for me, there are also a lot of
other changes in the new version. You can consult the
&lt;a class="reference external" href="https://github.com/onqtam/doctest/blob/master/CHANGELOG.md"&gt;changelog&lt;/a&gt; if you want more information.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Overall, doctest 1.1 is much faster to compile than doctest 1.0. Moreover, it
offers very fast macros for test assertions that are much faster to compile
than Catch versions and even faster than the versions I created myself to reduce
compilation time. I really thing this is a great advance for doctest. When
compiling with all the optimizations, doctest 1.1 saves me 50 seconds in
compilation time compared to the fast version of Catch macro and more than
5 minutes compared to the standard version of Catch macros.&lt;/p&gt;
&lt;p&gt;I'll probably start using doctest on my development machine. For now, I'll keep
Catch as well since I need it to generate the unit test reports in XML format
for Sonarqube. Once this feature appears in doctest, I'll probably drop Catch
from ETL and DLL&lt;/p&gt;
&lt;p&gt;If you need blazing fast compilation times for your unit tests, doctest 1.1 is
probably the way to go.&lt;/p&gt;
&lt;/section&gt;</description><category>C++</category><category>Catch</category><category>Compilers</category><category>doctest</category><category>etl</category><category>gcc</category><category>Performances</category><category>Tests</category><category>time</category><guid>https://baptiste-wicht.com/posts/2016/09/blazing-fast-unit-test-compilation-with-doctest-11.html</guid><pubDate>Wed, 21 Sep 2016 19:45:13 GMT</pubDate></item></channel></rss>