    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Type-agnostic Tracing Using {fmt}</title>
        <link>https://members.accu.org/index.php/articles/2509</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + Overload Journal #145 - June 2018</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c386/">o145</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-386/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+386/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Type-agnostic Tracing Using {fmt}</h1>
<p><strong>Author:</strong>&nbsp;Bob Schmidt</p>
<p>
<strong>Date:</strong> 03 June 2018 17:07:06 +01:00 or Sun, 03 June 2018 17:07:06 +01:00</p>
<p><strong>Summary:</strong>&nbsp;Tracing compound and custom types is a challenge. Mike Crowe demonstrates how {fmt} provides a safe alternative to printf.</p>
<p><strong>Body:</strong>&nbsp;<p>About eleven years ago, I was responsible for adding types that looked a bit like Listing 1 to a young C++ code base that lacked a standard way to do tracing for debugging. The implementation of <code>AlwaysTrace::operator()</code> wrote the trace message to an appropriate place.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
struct NeverTrace {
    void operator()(const char *, ...)
      __attribute__((format(printf, 2, 3))) {}
};

struct AlwaysTrace {
    void operator()(const char *, ...)
      __attribute__((format(printf, 2, 3)));
};

#if DEBUG&gt;0
typedef AlwaysTrace DebugTrace;
#else
typedef NeverTrace DebugTrace;
#endif
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 1</td>
	</tr>
</table>

<p>The intention was that each file could declare one or more instances of these types and use it throughout the code:</p>

<pre class="programlisting">
  static DebugTrace TRACE;
  void my_function(int i)
  {
    TRACE(&quot;A helpful message: %d\n&quot;, i);
  }</pre>
  
<p>The real classes had various other helpful functions of course, and eventually we ended up with a global <code>TRACE_ERROR</code> instance that would always be emitted.</p>

<p>This worked reasonably well, and although we always had plans to improve the mechanism, weâ€™ve never really got round to it. Some adornments to enable GCCâ€™s <code>printf</code> format string checking and using <code>-Werror</code> meant that the risk of getting the format string wrong was low. It was annoying to have to use <code>c_str()</code> when tracing <code>std::string</code> instances, but we just lived with that.</p>

<p>Iâ€™d always planned to support tracing compound and custom types by adding some iostreams-like functionality but I never got round to it. In any case, my coworkers and I were generally not keen on iostreams for its verbosity and other reasons recently well described in [<a href="#[Ignatchenko18]">Ignatchenko18</a>].</p>

<p>We continued to use these tracing classes for many years whilst targeting 32-bit MIPS and later ARM targets. We ended up with code like Listing 2.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
#include &lt;inttypes.h&gt;
void foo(uint64_t value)
{
  TRACE(&quot;foo passed %llu\n&quot;, value);
  //...
}
void bar(size_t length)
{
  TRACE(&quot;bar passed %zu\n&quot;, length);
  //...
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 2</td>
	</tr>
</table>

<p>This all worked fine, until we tried to compile for our first 64-bit target.</p>

<h2>The ugliness of &lt;inttypes.h&gt;</h2>

<p>The <code>&lt;inttypes.h&gt;</code> header (along with the <code>&lt;cinttypes&gt;</code> that we probably ought to have been using from C++) contains handy definitions for types with specific numbers of bits. It contains declarations like:</p>

<pre class="programlisting">
  #if defined(__LP64)
  typedef unsigned long uint64_t;
  typedef long int64_t;
  #else
  typedef unsigned long long uint64_t;
  typedef long long int64_t;
  #endif</pre>
  
<p>Unfortunately, this means that when compiling for a 32-bit target the <code>%llu</code> and <code>%lld</code> format specifiers are correct, but when compiling for a 64-bit target <code>%lu</code> and <code>%ld</code> must be used. <code>&lt;inttypes.h&gt;</code> provides the <code>PRIu64</code> and <code>PRId64</code> macros that expand to the correct form. Unfortunately, since they need to be used in a string literal, they are extremely ugly to use. (The full set of macros is at [<a href="#[CppRef]">CppRef</a>].)</p>

<p>The relatively sensible:</p>

<pre class="programlisting">
  void ReportProgress(uint64_t current, 
    uint64_t max)
  {
    TRACE(&quot;Progress %llu/%llu %llu%%\n&quot;, current,
      max, current * 100 / max);
  }</pre>
  
<p>becomes the hard-to-read, hard-to-type and hard-to-maintain:</p>

<pre class="programlisting">
  void ReportProgress(uint64_t current, 
    uint64_t max)
  {
    TRACE(&quot;Progress %&quot; PRIu64 &quot;/&quot; PRIu64 &quot; &quot; PRIu64
      &quot;%%\n&quot;, current, max, current * 100 / max);
  }</pre>
  
<p>So I went looking for an alternative and I found {fmt}.</p>

<h2>{fmt}</h2>

<p>The {fmt} library [<a href="#[fmt]">fmt</a>] provides a safe alternative to <code>printf</code>. It provides a Python-like formatting mechanism for C++, taking advantage of C++ type safety:</p>

<pre class="programlisting">
fmt::print(&quot;The {} is {}{}\n&quot;, &quot;answer&quot;, 42L, '.');</pre>

<p>But for me, the most interesting feature was its <code>printf</code>-compatible interface. When using this interface it will parse <code>printf</code> format strings, but mostly disregard the type information. This means that you can write:</p>

<pre class="programlisting">
  void ReportProgress(uint64_t current, 
   uint64_t max)
  {
    TRACE(&quot;Progress %u/%u %u%%\n&quot;, current, max,
      current * 100 / max);
  }</pre>
  
<p>without caring whether the three integers are <code>unsigned long</code> or <code>unsigned long long</code>, or any other integer type for that matter. This turned out to be the solution to my 64-bit tracing problem without needing to change all my code.</p>

<h2>Using fmt::printf</h2>

<p>The first step was to implement <code>AlwaysTrace::operator()</code> in terms of <code>fmt::printf</code> (see Listing 3).</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
struct NeverTrace {
  template &lt;typename... Args&gt;
  void operator()(const char *format,
    Args&amp;&amp;... args) {}
};
struct AlwaysTrace {
  template &lt;typename... Args&gt;
  void operator()(const char *format, 
    Args&amp;&amp;... Args) {
      fmt::printf(format,
        std::forward&lt;Args&gt;(args)...);
    }
};
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 3</td>
	</tr>
</table>

<h2>Catching exceptions</h2>

<p>This worked, but if I accidentally wrote:</p>

<pre class="programlisting">
  void ReportProgress(uint64_t current, 
    uint64_t max)
  {
    TRACE(&quot;Progress %d/%d%%\n&quot;, current);
  }</pre>
  
<p>then GCCâ€™s format string checker was no longer there to generate a compilation error; {fmt} would instead throw a <code>FormatError</code> exception. If there are too many parameters then it silently ignores the extra ones.</p>

<p>Tracing isnâ€™t important enough for us to want to risk terminating the program. This is especially important if tracing is not always enabled. I considered modifying {fmt} itself to stop it throwing, but that would mean disabling exception throwing even if we were to make use of the library in normal code too.</p>

<p>The simplest solution is to just catch exceptions and emit an error message along with the format string so that the offending line can be found and fixed (see Listing 4).</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
namespace wrapped {
  template &lt;typename... Args&gt;
  inline void printf(const char *format, 
      Args&amp;&amp;... args) {
    try {
      fmt::printf(format,
        std::forward&lt;Args&gt;(args)...);
    }
    catch (const std::exception &amp;e) {
      fmt::printf(&quot;Message '%s' threw '%s'\n&quot;,
        format, e.what());
    }
  }
}
struct AlwaysTrace {
  template &lt;typename... Args&gt;
  void operator()(const char *format, 
    Args&amp;&amp;... Args) {
      wrapped::printf(format,
        std::forward&lt;Args&gt;(args)...);
    }
};
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 4</td>
	</tr>
</table>

<p>Just before this article went to print, version 5 of {fmt} was released. This version supports compile-time verification of Python-style format strings [<a href="#[Zverovich17]">Zverovich17</a>]. I look forward to being able to take advantage of this to support both the Python-style format strings and validation whilst keeping the existing <code>printf</code>-compatible functions for existing code.</p>

<h2>Tracing errors</h2>

<p>In many places weâ€™d taken advantage of glibcâ€™s <code>%m</code> format specifier to print the error message associated with the current value of <code>errno</code>. The upstream maintainer didnâ€™t want to support such an extension [<a href="#[Crowe17a]">Crowe17a</a>], so I applied a local patch to do so. I hope to come up with something similar that will be acceptable upstream in the future.</p>

<h2>Tracing pointers</h2>

<p>In certain sections of the code there were a large number of places where the <code>this</code> pointer was emitted as part of a trace message. This helped to tie the tracing from multiple instances together when reading the logs. It used the <code>%p</code> format specifier for this.</p>

<p>The {fmt} library supports the <code>%p</code> format specifier, but the corresponding parameter must be of <code>const void *</code> or <code>void *</code> type. It has good reasons for this, at least some of which are described in [<a href="#[Wilson09]">Wilson09</a>]. On its branch hopefully destined for standardisation, it provides a <code>fmt::ptr</code>` helper to cast arbitrary pointers to an acceptable type.</p>

<p>Unfortunately, I had lots of code using <code>%p</code> and casting all the corresponding parameters was painful. I decided to patch {fmt} locally to support arbitrary pointers [<a href="#[Crowe17b]">Crowe17b</a>], despite the downsides. The upstream maintainer seems favourable to supporting this in the <code>printf</code>-compatible case only, if only I can find a clean way to do so.</p>

<h2>Effect on compilation time and binary size</h2>

<p>Of course, all this magic has to come at a cost. In my not-hugely-scientific experiments, on a project that contained about 7500 trace statements, compilation and linking with GCC of debug builds (with <code>-g3</code>) took about 5% longer. The same with <code>-O2</code> and <code>-g3</code> only took about 1% longer. So, whilst there is an effect, itâ€™s not huge.</p>

<p>This code runs on an embedded system, albeit one with over a gigabyte of memory, but nonetheless the size of the generated code was a concern. Without making any attempt to catch exceptions the stripped binary was about 0.75% bigger. When catching exceptions it was about 1.5% bigger. </p>

<h2>Enabling new behaviours</h2>

<p>Now that weâ€™re using the library, we no longer have to care about the exact types of integers weâ€™re tracing, and can pass <code>std::string</code> without calling <code>c_str()</code>, which is a bonus. We no longer have to be picky about the exact type of integers either. In new code we donâ€™t have to remember to say <code>%zu</code> when tracing a <code>size_t</code>.</p>

<h2>Tracing custom types</h2>

<p>We end up tracing <code>std::chrono</code> types in quite a few places. We can define a custom formatter with something like Listing 5, then write code like:</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
namespace fmt {
    /// Displays in microseconds or seconds
    template &lt;typename Rep, typename Period&gt;
    void format_arg(fmt::BasicFormatter&lt;char&gt; &amp;f,
      const char *&amp;format_str,
      const std::chrono::duration&lt;Rep, Period&gt;
        &amp;duration)
      {
        if (duration &lt; std::chrono::seconds(1))
          f.writer().write(&quot;{}us&quot;,
          std::chrono::duration&lt;double,
          std::micro&gt;(duration).count());
        else
          f.writer().write(&quot;{}s&quot;,
          std::chrono::duration&lt;double&gt;(duration)
            .count());
      }
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 5</td>
	</tr>
</table>

<pre class="programlisting">
  void f() {
    auto start = std::chrono::steady_clock::now();
    do_something_time_consuming();
    auto duration = 
      std::chrono::steady_clock::now() - start;
    TRACE(&quot;It took %ldms\n&quot;, duration);
  }</pre>

<h2>The future</h2>

<p>Victor Zverovich, the primary author of the {fmt} library, has proposed the Python-style format strings subset of the library for standardisation and presented his work at the Jacksonville WG21 meeting [<a href="#[WG21]">WG21</a>]. Iâ€™m keen to see how it can be used to improve our tracing in the future.</p>

<h2>Thanks</h2>

<p>Thanks to Victor Zverovich, the primary author of {fmt}, for reviewing draft versions of this article and for helping with my attempts to mould it to our needs.</p>

<p>Thanks to Frances Buontempo and the <em>Overload</em> reviewers for their suggestions and advice.</p>

<h2>References</h2>

<p class="bibliomixed"><a id="[CppRef]"></a>[CppRef] â€˜Fixed width integer typesâ€™ available at: <a href="http://en.cppreference.com/w/cpp/types/integer">http://en.cppreference.com/w/cpp/types/integer</a></p>

<p class="bibliomixed"><a id="[Crowe17a]"></a>[Crowe17a] Mike Crowe (2017) â€˜printf: Add support for glibcâ€™s %m formatâ€™ at <a href="https://github.com/fmtlib/fmt/pull/550">https://github.com/fmtlib/fmt/pull/550</a>, posted 22 July 2017</p>

<p class="bibliomixed"><a id="[Crowe17b]"></a>[Crowe17b] Mike Crowe (2017) â€˜What are the downsides to disabling the private MakeValue::MakeValue&lt;T*&gt; overloads?â€™ at <a href="https://github.com/fmtlib/fmt/issues/608">https://github.com/fmtlib/fmt/issues/608</a>, posted 11 November 2017</p>

<p class="bibliomixed"><a id="[fmt]"></a>[fmt] The {fmt} library <a href="http://fmtlib.net">http://fmtlib.net</a></p>

<p class="bibliomixed"><a id="[Ignatchenko18]"></a>[Ignatchenko18] Sergey Ignatchenko (2018) â€˜This is NOT yet another printf-vs-cout debateâ€™ in <em>Overload</em> 144, April 2018, available at: <a href="https://accu.org/index.php/journals/2486">https://accu.org/index.php/journals/2486</a></p>

<p class="bibliomixed"><a id="[WG21]"></a>[WG21] â€˜Text Formatting at the ISO C++ standards meeting in Jacksonvilleâ€™, available online at <a href="http://www.zverovich.net/2018/03/17/text-formatting-jacksonville.html">http://www.zverovich.net/2018/03/17/text-formatting-jacksonville.html</a></p>

<p class="bibliomixed"><a id="[Wilson09]"></a>[Wilson09] Matthew Wilson (2009) â€˜An Introduction to Fast Format (Part 1): The State of the Artâ€™, <em>Overload</em> 89, available at <a href="https://accu.org/index.php/journals/1539">https://accu.org/index.php/journals/1539</a></p>

<p class="bibliomixed"><a id="[Zverovich17]"></a>[Zverovich17] Victor Zverovich (2017) Verification of Python-style format strings: <a href="http://zverovich.net/2017/11/05/compile-time-format-strings.html">http://zverovich.net/2017/11/05/compile-time-format-strings.html</a></p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
