<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Georg's Log - linux</title><link href="https://gms.tf/" rel="alternate"></link><link href="https://gms.tf/feeds/linux.atom.xml" rel="self"></link><id>https://gms.tf/</id><updated>2026-03-29T18:00:00+02:00</updated><entry><title>Better Datamash Build Story with Meson</title><link href="https://gms.tf/datamash-meson.html" rel="alternate"></link><published>2026-03-29T18:00:00+02:00</published><updated>2026-03-29T18:00:00+02:00</updated><author><name>Georg Sauthoff</name></author><id>tag:gms.tf,2026-03-29:/datamash-meson.html</id><summary type="html">&lt;p&gt;This article is a small case study on introducing the &lt;a href="https://en.wikipedia.org/wiki/Meson_(software)"&gt;Meson&lt;/a&gt; build
tool into a legacy &lt;a href="https://en.wikipedia.org/wiki/GNU_Autotools"&gt;Autotools&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Gnulib"&gt;Gnulib&lt;/a&gt; centric code base, i.e.
the &lt;a href="https://www.gnu.org/software/datamash/"&gt;GNU Datamash&lt;/a&gt; project.
With Meson, the &lt;a href="https://opencommit.eu/gms/datamash/commits/branch/main"&gt;result&lt;/a&gt; builds twice as fast and configures one order of magnitude faster
while only requiring a few hundred lines …&lt;/p&gt;</summary><content type="html">&lt;p&gt;This article is a small case study on introducing the &lt;a href="https://en.wikipedia.org/wiki/Meson_(software)"&gt;Meson&lt;/a&gt; build
tool into a legacy &lt;a href="https://en.wikipedia.org/wiki/GNU_Autotools"&gt;Autotools&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Gnulib"&gt;Gnulib&lt;/a&gt; centric code base, i.e.
the &lt;a href="https://www.gnu.org/software/datamash/"&gt;GNU Datamash&lt;/a&gt; project.
With Meson, the &lt;a href="https://opencommit.eu/gms/datamash/commits/branch/main"&gt;result&lt;/a&gt; builds twice as fast and configures one order of magnitude faster
while only requiring a few hundred lines of Meson build files.
As as side-effect of this experiment the size of the executables is halved.&lt;/p&gt;
&lt;div class="toc"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#on-datamash"&gt;On Datamash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#on-meson"&gt;On Meson&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#motivation"&gt;Motivation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#configure"&gt;Configure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#build"&gt;Build&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#code-size"&gt;Code Size&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#on-gnulib"&gt;On Gnulib&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#source-overhead"&gt;Source Overhead&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#test-suite"&gt;Test Suite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#side-effects"&gt;Side Effects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#see-also"&gt;See also&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#conclusion"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id="on-datamash"&gt;On Datamash&lt;a class="headerlink" href="#on-datamash" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.gnu.org/software/datamash/"&gt;Datamash&lt;/a&gt; is a command line program for running various statistics
on tabular data, such as computing the count, average or
median of a column.&lt;/p&gt;
&lt;p&gt;Its sweet-spot seems to be ad-hoc analyses on the command line,
on systems where installing a more heavy-weight alternative such as &lt;a href="https://en.wikipedia.org/wiki/R_(programming_language)"&gt;R&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/DuckDB"&gt;DuckDB&lt;/a&gt; would be too inconvenient.&lt;/p&gt;
&lt;p&gt;In the following comparisons, I compare Datamash 1.9, released in the first half of 2025,
against my &lt;a href="https://opencommit.eu/gms/datamash/commits/branch/main"&gt;datamash 'main' branch&lt;/a&gt; which has Meson support and a few other fixes and improvements added,
and is based on the end of 2025 upstream 'master' branch, i.e. release 1.9 plus just a few minor upstream commits.&lt;/p&gt;
&lt;h2 id="on-meson"&gt;On Meson&lt;a class="headerlink" href="#on-meson" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://mesonbuild.com/"&gt;Meson&lt;/a&gt; is modern build tool that is an alternative to autotools
and CMake. See also my 2021 &lt;a href="the-rise-of-meson.html#about-meson"&gt;summary of meson&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="motivation"&gt;Motivation&lt;a class="headerlink" href="#motivation" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Meson_(software)"&gt;Meson&lt;/a&gt; design improves on pain points many users often
have with &lt;a href="https://en.wikipedia.org/wiki/GNU_Autotools"&gt;Autotools&lt;/a&gt;, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;configure wasting time checking for tons of things that are true
  everywhere since decades (and doing so single-threaded)&lt;/li&gt;
&lt;li&gt;build wasting time with inefficient auto-generated recursive
  makefiles&lt;/li&gt;
&lt;li&gt;layers of &lt;a href="https://en.wikipedia.org/wiki/M4_(computer_language)"&gt;m4&lt;/a&gt; and shell scripting are involved which results in a
  &lt;a href="https://en.wikipedia.org/wiki/Spaghetti_code#Big_ball_of_mud"&gt;big ball of mud&lt;/a&gt;
  that easily breaks and is hard to fix or work on, in general&lt;/li&gt;
&lt;li&gt;all the Autotools generated project specific code being hard to
  review and being an invitation for &lt;a href="https://en.wikipedia.org/wiki/Supply_chain_attack"&gt;supply chain attackers&lt;/a&gt; such as &lt;a href="https://en.wikipedia.org/wiki/XZ_Utils_backdoor"&gt;Jia Tan&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The idea with Meson is that it eliminates all these issues,
in particular that it speeds up the build, makes the project specific build files
easier to review, reduces maintenance efforts and simplifies
working with the build system, in general.&lt;/p&gt;
&lt;h2 id="configure"&gt;Configure&lt;a class="headerlink" href="#configure" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Using the Datamash 1.9 release, running &lt;code&gt;./configure&lt;/code&gt; takes &lt;strong&gt;13 s&lt;/strong&gt; or
so on a modern laptop (12th Gen Intel CPU, NVMe storage, Fedora 43).
That configure triggers 488 checks which seems excessive.&lt;/p&gt;
&lt;p&gt;Some things are checked redundantly which &lt;a href="https://en.wikipedia.org/wiki/Autoconf"&gt;autoconf&lt;/a&gt; tries to
mitigate via caching the results, such as checks for &lt;code&gt;round()&lt;/code&gt;:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;checking whether round is declared... yes
checking whether round works... yes
checking whether roundl is declared... yes
checking whether round is declared... (cached) yes
checking whether round works... (cached) yes
checking whether roundl is declared... (cached) yes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For some reason, other checks are invoked up to two times:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;checking for stdint.h... yes
checking whether stdint.h conforms to C99... yes
checking whether stdint.h works without ISO C predefines... yes
checking whether stdint.h has UINTMAX_WIDTH etc.... yes
checking for stdint.h... yes
checking for stdint.h... (cached) yes
checking for stdint.h... (cached) yes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In total there are 30 cached checks.&lt;/p&gt;
&lt;p&gt;Some more examples of surprising checks:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="go"&gt;checking whether strdup is declared... yes&lt;/span&gt;
&lt;span class="go"&gt;checking whether strnlen is declared... yes&lt;/span&gt;
&lt;span class="go"&gt;checking for strnlen... yes&lt;/span&gt;
&lt;span class="go"&gt;checking for working strnlen... yes&lt;/span&gt;
&lt;span class="go"&gt;checking for strtold... yes&lt;/span&gt;
&lt;span class="go"&gt;checking for strtoumax... yes&lt;/span&gt;
&lt;span class="go"&gt;checking whether strtoumax is declared... yes&lt;/span&gt;
&lt;span class="go"&gt;checking whether strtod obeys C99... yes&lt;/span&gt;
&lt;span class="go"&gt;checking whether strtold obeys POSIX... yes&lt;/span&gt;
&lt;span class="go"&gt;checking for strtoll... yes&lt;/span&gt;
&lt;span class="go"&gt;checking whether strtoll works... yes&lt;/span&gt;
&lt;span class="go"&gt;checking for strtoull... yes&lt;/span&gt;
&lt;span class="go"&gt;checking whether strtoull works... yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These are covered since either &lt;a href="https://en.wikipedia.org/wiki/ANSI_C#C89"&gt;C89&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/ANSI_C#C99"&gt;C99&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/POSIX#POSIX.1-2001"&gt;POSIX.1.-2001&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/POSIX#POSIX.1-2008"&gt;POSIX.1-2008&lt;/a&gt;.
I mean, how realistic is it that there are actually
Datamash users who want to install the latests greatest datamash,
but run such a broken and vulnerable operating system that lacks support
for theses decades old standards.&lt;/p&gt;
&lt;p&gt;Sure, &lt;a href="https://en.wikipedia.org/wiki/Retrocomputing"&gt;retrocomputing&lt;/a&gt; can be fun, but isn't the point of
retrocomputing to run &lt;em&gt;old&lt;/em&gt; software?&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In comparison, the Meson checks concentrate on the essentials
such that the setup finishes in &lt;strong&gt;0.5 s&lt;/strong&gt; or so!
Meaning an order of magnitude faster.
Also, the output volume is lower and thus more useful:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;meson&lt;span class="w"&gt; &lt;/span&gt;setup&lt;span class="w"&gt; &lt;/span&gt;--buildtype&lt;span class="o"&gt;=&lt;/span&gt;debugoptimized&lt;span class="w"&gt; &lt;/span&gt;..
&lt;span class="go"&gt;The Meson build system&lt;/span&gt;
&lt;span class="go"&gt;Version: 1.8.5&lt;/span&gt;
&lt;span class="go"&gt;Source dir: /home/juser/del/datamash&lt;/span&gt;
&lt;span class="go"&gt;Build dir: /home/juser/del/datamash/build&lt;/span&gt;
&lt;span class="go"&gt;Build type: native build&lt;/span&gt;
&lt;span class="go"&gt;Project name: datamash&lt;/span&gt;
&lt;span class="go"&gt;Project version: undefined&lt;/span&gt;
&lt;span class="go"&gt;C compiler for the host machine: cc (gcc 15.2.1 &amp;quot;cc (GCC) 15.2.1 20260123 (Red Hat 15.2.1-7)&amp;quot;)&lt;/span&gt;
&lt;span class="go"&gt;C linker for the host machine: cc ld.bfd 2.45.1-1&lt;/span&gt;
&lt;span class="go"&gt;Host machine cpu family: x86_64&lt;/span&gt;
&lt;span class="go"&gt;Host machine cpu: x86_64&lt;/span&gt;
&lt;span class="go"&gt;Library m found: YES&lt;/span&gt;
&lt;span class="go"&gt;Found pkg-config: YES (/usr/bin/pkg-config) 2.3.0&lt;/span&gt;
&lt;span class="go"&gt;Run-time dependency nettle found: YES 3.10.1&lt;/span&gt;
&lt;span class="go"&gt;Compiler for C supports function attribute alloc_size: YES&lt;/span&gt;
&lt;span class="go"&gt;Compiler for C supports function attribute cold: YES&lt;/span&gt;
&lt;span class="go"&gt;Compiler for C supports function attribute const: YES&lt;/span&gt;
&lt;span class="go"&gt;Fetching value of define &amp;quot;__has_c_attribute(fallthrough)&amp;quot; : 202311&lt;/span&gt;
&lt;span class="go"&gt;Compiler for C supports function attribute format: YES&lt;/span&gt;
&lt;span class="go"&gt;Compiler for C supports function attribute malloc: YES&lt;/span&gt;
&lt;span class="go"&gt;Compiler for C supports function attribute warn_unused_result: YES&lt;/span&gt;
&lt;span class="go"&gt;Compiler for C supports function attribute pure: YES&lt;/span&gt;
&lt;span class="go"&gt;Compiler for C supports function attribute returns_nonnull: YES&lt;/span&gt;
&lt;span class="go"&gt;Compiler for C supports function attribute sentinel: YES&lt;/span&gt;
&lt;span class="go"&gt;Checking for function &amp;quot;strtoumax&amp;quot; : YES&lt;/span&gt;
&lt;span class="go"&gt;Configuring config.h using configuration&lt;/span&gt;
&lt;span class="go"&gt;Program ./tests/datamash-tests.pl found: YES (/home/juser/del/datamash/./tests/datamash-tests.pl)&lt;/span&gt;
&lt;span class="go"&gt;[..]&lt;/span&gt;
&lt;span class="go"&gt;Program ./tests/decorate-sort-tests.pl found: YES (/usr/bin/env perl /home/juser/del/datamash/./tests/decorate-sort-tests.pl)&lt;/span&gt;
&lt;span class="go"&gt;Program perl found: YES (/usr/bin/perl)&lt;/span&gt;
&lt;span class="go"&gt;Program sh found: YES (/usr/bin/sh)&lt;/span&gt;
&lt;span class="go"&gt;Program msgfmt found: YES (/usr/bin/msgfmt)&lt;/span&gt;
&lt;span class="go"&gt;Program msginit found: YES (/usr/bin/msginit)&lt;/span&gt;
&lt;span class="go"&gt;Program msgmerge found: YES (/usr/bin/msgmerge)&lt;/span&gt;
&lt;span class="go"&gt;Program xgettext found: YES (/usr/bin/xgettext)&lt;/span&gt;
&lt;span class="go"&gt;Program help2man found: YES (/usr/bin/help2man)&lt;/span&gt;
&lt;span class="go"&gt;Configuring version.texi using configuration&lt;/span&gt;
&lt;span class="go"&gt;Program makeinfo found: YES (/usr/bin/makeinfo)&lt;/span&gt;
&lt;span class="go"&gt;Build targets in project: 22&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The check for &lt;code&gt;strtoumax&lt;/code&gt; is included as an example how easy it's
to implement such a check in Meson, if you really need it.&lt;/p&gt;
&lt;h2 id="build"&gt;Build&lt;a class="headerlink" href="#build" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Allowing the make to run on 2 cores in parallel, the datamash
autotools build finishes in &lt;strong&gt;4 s&lt;/strong&gt; or so.&lt;/p&gt;
&lt;p&gt;Looking at the build messages, there are a few oddities:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;gcc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;DLOCALEDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;\&lt;span class="s2"&gt;&amp;quot;/home/juser/local/datamash-1.9/share/locale&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s2"&gt; -DHAVE_CONFIG_H -I.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Ilib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Isrc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wall&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wextra&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wformat&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;security&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wswitch&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wswitch&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wunused&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;parameter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wfloat&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;equal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;fdiagnostics&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;option&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;funit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wmissing&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wstrict&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;overflow&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wsuggest&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wsuggest&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pure&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;O2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;MT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;MD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;MP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;MF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/.&lt;/span&gt;&lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tpo&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;src/column-headers.c&amp;#39;&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="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./&amp;#39;&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There is an extra shell invocation for each translation unit,
which seems to be pointless, as you either end up with&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;gcc ... -c -o src/foo.o src/foo.c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;or&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;gcc ... -c -o src/foo.o ./src/foo.c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There is also some redundancy in linking to &lt;code&gt;-lm&lt;/code&gt;:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;gcc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wall&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wextra&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wformat&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;security&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wswitch&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wswitch&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wunused&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;parameter&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wfloat&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;equal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;fdiagnostics&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;funit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wmissing&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wstrict&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;overflow&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wsuggest&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Wsuggest&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pure&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;O2&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;randutils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;defs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;scanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ops&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;crosstab&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;double&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;datamash&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;libdatamash&lt;/span&gt;&lt;span class="o"&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="n"&gt;lm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lm&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lm&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Meaning for unknown reasons Autotools links 16 times to libm.
Arguably, this is a good example of how even Autotools fans
struggle with its complexity and are overwhelmed by it.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In comparison, Meson builds everything in &lt;strong&gt;1.5 s&lt;/strong&gt; or so (i.e. more
than twice as fast) and its default output is more reasonable.
That means by default the user isn't spammed with overly long and
cryptic low-level command invocations, but useful high-level
progress:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;ninja&lt;span class="w"&gt; &lt;/span&gt;-j2&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="go"&gt;[1/50] Compiling C object datamash.p/src_column-headers.c.o&lt;/span&gt;
&lt;span class="go"&gt;[2/50] Compiling C object datamash.p/src_crosstab.c.o&lt;/span&gt;
&lt;span class="go"&gt;[..]&lt;/span&gt;
&lt;span class="go"&gt;[15/50] Compiling C object datamash.p/_usr_share_gnulib_lib_hashcode-mem.c.o&lt;/span&gt;
&lt;span class="go"&gt;[16/50] Compiling C object datamash.p/_usr_share_gnulib_lib_hashcode-string2.c.o&lt;/span&gt;
&lt;span class="go"&gt;[..]&lt;/span&gt;
&lt;span class="go"&gt;[31/50] Linking target datamash&lt;/span&gt;
&lt;span class="go"&gt;[32/50] Building translation po/da/LC_MESSAGES/datamash-da.mo&lt;/span&gt;
&lt;span class="go"&gt;[33/50] Building translation po/de/LC_MESSAGES/datamash-de.mo&lt;/span&gt;
&lt;span class="go"&gt;[34/50] Compiling C object decorate.p/_usr_share_gnulib_lib_xmalloc.c.o&lt;/span&gt;
&lt;span class="go"&gt;[35/50] Building translation po/eo/LC_MESSAGES/datamash-eo.mo&lt;/span&gt;
&lt;span class="go"&gt;[..]&lt;/span&gt;
&lt;span class="go"&gt;[40/50] Linking target decorate&lt;/span&gt;
&lt;span class="go"&gt;[48/50] Generating datamash manual with a custom command (wrapped by meson to set env)&lt;/span&gt;
&lt;span class="go"&gt;[49/50] Generating decorate manual with a custom command (wrapped by meson to set env)&lt;/span&gt;
&lt;span class="go"&gt;[50/50] Generating gen-info with a custom command&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Of course, when a command errors out the full command line and
error message are presented to the user and alternatively, one
can run the build in verbose mode by adding &lt;code&gt;-v&lt;/code&gt; to the ninja
command.&lt;/p&gt;
&lt;p&gt;The verbose mode doesn't slow down the build noticeable.
Enabling it shows that meson doesn't have the same issues with
linking libm:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cc  -o datamash
    datamash.p/src_column-headers.c.o datamash.p/src_crosstab.c.o datamash.p/src_datamash.c.o
    datamash.p/src_double-format.c.o datamash.p/src_field-ops.c.o datamash.p/src_op-defs.c.o
    datamash.p/src_op-parser.c.o datamash.p/src_op-scanner.c.o datamash.p/src_randutils.c.o
    datamash.p/src_text-lines.c.o datamash.p/src_text-options.c.o datamash.p/src_utils.c.o
    datamash.p/modern_system.c.o datamash.p/_usr_share_gnulib_lib_exitfail.c.o
    datamash.p/_usr_share_gnulib_lib_hash.c.o datamash.p/_usr_share_gnulib_lib_hashcode-mem.c.o
    datamash.p/_usr_share_gnulib_lib_hashcode-string2.c.o datamash.p/_usr_share_gnulib_lib_linebuffer.c.o
    datamash.p/_usr_share_gnulib_lib_next-prime.c.o datamash.p/_usr_share_gnulib_lib_version-etc.c.o
    datamash.p/_usr_share_gnulib_lib_xalloc-die.c.o datamash.p/_usr_share_gnulib_lib_xmalloc.c.o
    -Wl,--as-needed -Wl,--no-undefined -Wl,--start-group -lm /usr/lib64/libnettle.so -Wl,--end-group
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In contrast to the Autotools status quo, I decided against creating a static library of the Gnulib parts,
since the effort doesn't pay off, because it's only used by two executables.
Instead I link only those Gnulib translation units directly which are essential for each binary.&lt;/p&gt;
&lt;h2 id="code-size"&gt;Code Size&lt;a class="headerlink" href="#code-size" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Comparing the sizes of executables in the Datamash 1.9 vs. Meson branch shows substantial
savings with Meson (all sizes in bytes, via &lt;code&gt;size -G&lt;/code&gt;):&lt;/p&gt;
&lt;table class="m-table"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;branch&lt;/th&gt;
&lt;th&gt;filename&lt;/th&gt;
&lt;th&gt;&lt;a href="https://en.wikipedia.org/wiki/Code_segment"&gt;text&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://en.wikipedia.org/wiki/Data_segment"&gt;data&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://en.wikipedia.org/wiki/.bss"&gt;bss&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1.9&lt;/td&gt;
&lt;td&gt;datamash&lt;/td&gt;
&lt;td&gt;97370&lt;/td&gt;
&lt;td&gt;42120&lt;/td&gt;
&lt;td&gt;968&lt;/td&gt;
&lt;td&gt;140458&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;meson&lt;/td&gt;
&lt;td&gt;datamash&lt;/td&gt;
&lt;td&gt;46736&lt;/td&gt;
&lt;td&gt;35756&lt;/td&gt;
&lt;td&gt;640&lt;/td&gt;
&lt;td&gt;83132&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.9&lt;/td&gt;
&lt;td&gt;decorate&lt;/td&gt;
&lt;td&gt;27348&lt;/td&gt;
&lt;td&gt;22068&lt;/td&gt;
&lt;td&gt;1576&lt;/td&gt;
&lt;td&gt;50992&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;meson&lt;/td&gt;
&lt;td&gt;decorate&lt;/td&gt;
&lt;td&gt;15520&lt;/td&gt;
&lt;td&gt;16224&lt;/td&gt;
&lt;td&gt;1248&lt;/td&gt;
&lt;td&gt;32992&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;That means that the code size of the datamash executable is reduced by over &lt;strong&gt;50 percent&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;These space savings are due to only linking those parts of &lt;a href="https://en.wikipedia.org/wiki/Gnulib"&gt;Gnulib&lt;/a&gt; that are essential,
i.e. Datamash 1.9 links the following 120 Gnulib translation units:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="go"&gt;af_alg.c                        hash-pjw-bare.c                 stat-time.c&lt;/span&gt;
&lt;span class="go"&gt;arpa_inet.c                     hash-pjw.c                      stdlib.c&lt;/span&gt;
&lt;span class="go"&gt;asnprintf.c                     ialloc.c                        striconv.c&lt;/span&gt;
&lt;span class="go"&gt;base64.c                        imaxtostr.c                     stripslash.c&lt;/span&gt;
&lt;span class="go"&gt;basename.c                      inttostr.c                      strnlen1.c&lt;/span&gt;
&lt;span class="go"&gt;basename-lgpl.c                 linebuffer.c                    sys_socket.c&lt;/span&gt;
&lt;span class="go"&gt;bitrotate.c                     localcharset.c                  trim.c&lt;/span&gt;
&lt;span class="go"&gt;c32isalnum.c                    localename.c                    u64.c&lt;/span&gt;
&lt;span class="go"&gt;c32isalpha.c                    localename-environ.c            uinttostr.c&lt;/span&gt;
&lt;span class="go"&gt;c32isblank.c                    localename-table.c              umaxtostr.c&lt;/span&gt;
&lt;span class="go"&gt;c32iscntrl.c                    localename-unsafe.c             unicase/tolower.c&lt;/span&gt;
&lt;span class="go"&gt;c32isdigit.c                    malloca.c                       unictype/ctype_alnum.c&lt;/span&gt;
&lt;span class="go"&gt;c32isgraph.c                    math.c                          unictype/ctype_alpha.c&lt;/span&gt;
&lt;span class="go"&gt;c32islower.c                    mbchar.c                        unictype/ctype_blank.c&lt;/span&gt;
&lt;span class="go"&gt;c32isprint.c                    mbrtoc32.c                      unictype/ctype_cntrl.c&lt;/span&gt;
&lt;span class="go"&gt;c32ispunct.c                    mbrtowc.c                       unictype/ctype_digit.c&lt;/span&gt;
&lt;span class="go"&gt;c32isspace.c                    mbslen.c                        unictype/ctype_graph.c&lt;/span&gt;
&lt;span class="go"&gt;c32isupper.c                    mbsstr.c                        unictype/ctype_lower.c&lt;/span&gt;
&lt;span class="go"&gt;c32isxdigit.c                   mbszero.c                       unictype/ctype_print.c&lt;/span&gt;
&lt;span class="go"&gt;c32tolower.c                    mbuiter.c                       unictype/ctype_punct.c&lt;/span&gt;
&lt;span class="go"&gt;c32width.c                      mbuiterf.c                      unictype/ctype_space.c&lt;/span&gt;
&lt;span class="go"&gt;c-ctype.c                       md5.c                           unictype/ctype_upper.c&lt;/span&gt;
&lt;span class="go"&gt;cloexec.c                       md5-stream.c                    unictype/ctype_xdigit.c&lt;/span&gt;
&lt;span class="go"&gt;closeout.c                      offtostr.c                      unistd.c&lt;/span&gt;
&lt;span class="go"&gt;close-stream.c                  printf-args.c                   unistr/u8-mbtoucr.c&lt;/span&gt;
&lt;span class="go"&gt;c-strcasecmp.c                  printf-parse.c                  unistr/u8-uctomb-aux.c&lt;/span&gt;
&lt;span class="go"&gt;dirname.c                       progname.c                      unistr/u8-uctomb.c&lt;/span&gt;
&lt;span class="go"&gt;dirname-lgpl.c                  propername.c                    uniwidth/width.c&lt;/span&gt;
&lt;span class="go"&gt;exitfail.c                      quotearg.c                      vasnprintf.c&lt;/span&gt;
&lt;span class="go"&gt;fcntl.c                         reallocarray.c                  version-etc.c&lt;/span&gt;
&lt;span class="go"&gt;fd-hook.c                       realloc.c                       vsnzprintf.c&lt;/span&gt;
&lt;span class="go"&gt;fpurge.c                        setlocale_null.c                wctype-h.c&lt;/span&gt;
&lt;span class="go"&gt;freading.c                      setlocale_null-unlocked.c       xalloc-die.c&lt;/span&gt;
&lt;span class="go"&gt;getlocalename_l-unsafe.c        sha1.c                          xmalloc.c&lt;/span&gt;
&lt;span class="go"&gt;getprogname.c                   sha1-stream.c                   xsize.c&lt;/span&gt;
&lt;span class="go"&gt;glthread/lock.c                 sha256.c                        xstriconv.c&lt;/span&gt;
&lt;span class="go"&gt;glthread/once.c                 sha256-stream.c                 xstrtol.c&lt;/span&gt;
&lt;span class="go"&gt;glthread/threadlib.c            sha512.c                        xstrtol-error.c&lt;/span&gt;
&lt;span class="go"&gt;hard-locale.c                   sha512-stream.c                 xstrtoul.c&lt;/span&gt;
&lt;span class="go"&gt;hash.c                          sh-quote.c                      xstrtoumax.c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;While the Meson branch only links the following 9 Gnulib translation units:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="go"&gt;exitfail.c&lt;/span&gt;
&lt;span class="go"&gt;hash.c&lt;/span&gt;
&lt;span class="go"&gt;hashcode-mem.c&lt;/span&gt;
&lt;span class="go"&gt;hashcode-string2.c&lt;/span&gt;
&lt;span class="go"&gt;linebuffer.c&lt;/span&gt;
&lt;span class="go"&gt;next-prime.c&lt;/span&gt;
&lt;span class="go"&gt;version-etc.c&lt;/span&gt;
&lt;span class="go"&gt;xalloc-die.c&lt;/span&gt;
&lt;span class="go"&gt;xmalloc.c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The following measures make this reduction possible:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Identifying Gnulib functionality that is widely available in the standard library
   or in quasi-standard libraries and use that instead of Gnulib.&lt;/li&gt;
&lt;li&gt;Removal of accidental code bloat.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For example, after &lt;a href="https://opencommit.eu/gms/datamash/commit/9a7b5e271e6d000cf9c9db2587c6fb7355726a6d"&gt;fixing the percentile computation&lt;/a&gt;, I was able to replace the separate &lt;a href="https://opencommit.eu/gms/datamash/commit/27ee8d1995a8032bb579454140225612636afd5c"&gt;median implementation&lt;/a&gt; with an alias that saves 200 bytes or so in code size.&lt;/p&gt;
&lt;p&gt;Since &lt;a href="https://en.wikipedia.org/wiki/Nettle_(cryptographic_library)"&gt;libnettle&lt;/a&gt; is widely available and often pre-installed as core system dependency,
it suggests itself for the cryptographic hash and base64 computations in datamash instead of &lt;a href="https://en.wiktionary.org/wiki/vendor#Verb"&gt;vendoring&lt;/a&gt; in the Gnulib versions.
&lt;a href="https://opencommit.eu/gms/datamash/commit/63f234ec7ff33d81af82f3772f09e4ef8a9d7598"&gt;Switching to libnettle&lt;/a&gt;
is a moderate source code change but saves several kilobytes in the executable.&lt;/p&gt;
&lt;p&gt;Another source of Gnulib over-usage is quoting, i.e. after &lt;a href="https://opencommit.eu/gms/datamash/commit/df9e598b89c00483d0e8221ca866717e33195355"&gt;replacing a popen&lt;/a&gt; invocation with an idiomatic direct fork and exec sequence, we can get rid of Gnulib's &lt;code&gt;sh-quote.c&lt;/code&gt; translation unit and its dependency hell.
Similarly, to me a &lt;a href="https://opencommit.eu/gms/datamash/commit/b4a30543833c89bc70099cf003001b598be57b37"&gt;minimal quoting implementation&lt;/a&gt; in the datamash decorate command is preferable as it's more size efficient and easier to review.&lt;/p&gt;
&lt;p&gt;One more code bloat source is how Datamash 1.9 quotes trivial arguments in error messages, i.e. via a Gnulib function that quotes in a localized fashion. I don't think that this is worth it and thus switched the branch to a &lt;a href="https://opencommit.eu/gms/datamash/src/commit/1fc869a607497c7a366af9d8a18abf5d3d8ddd87/modern/system.c"&gt;more minimal version&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In another example, I changed the code into invoking the standardized &lt;a href="https://opencommit.eu/gms/datamash/commit/36768af613dca2c92b2b24e78062c5991d44d980"&gt;strtoumax&lt;/a&gt; instead of using the closely named but non-conforming Gnulib version.&lt;/p&gt;
&lt;p&gt;Besides code sizes, Gnulib versions are always suspect to being less battle-tested and optimized,
and when bugs are fixed in them, it's easy to miss updates, i.e. in contrast to a shared system library,
as Gnulib is designed to be &lt;a href="https://en.wiktionary.org/wiki/vendor#Verb"&gt;vendored&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Of course, the code changes aren't really Meson specific,
but I argue that the way I integrated the Gnulib dependencies into to Meson build file simplified
those changes vs. having to hack the autotools Gnulib integration to link only the essential translation units.&lt;/p&gt;
&lt;h2 id="on-gnulib"&gt;On Gnulib&lt;a class="headerlink" href="#on-gnulib" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Gnulib"&gt;Gnulib&lt;/a&gt; describes itself as source-code library and a user is supposed to &lt;a href="https://en.wiktionary.org/wiki/vendor#Verb"&gt;vendor&lt;/a&gt; the gnulib parts one
needs into a project (i.e. copy and bundle gnulib source code files with his/her project).&lt;/p&gt;
&lt;p&gt;Although the Gnulib manual has a few paragraphs on its philosophy and design, it doesn't give &lt;em&gt;any&lt;/em&gt; rationale for &lt;em&gt;that&lt;/em&gt; odd design decision. It &lt;a href="https://www.gnu.org/software/gnulib/manual/gnulib.html#Library-vs_002e-Reusable-Code"&gt;just states&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Classical libraries are installed as binary object code. Gnulib is different: It is used as a source code library. Each package that uses Gnulib thus ships with part of the Gnulib source code. The used portion of Gnulib is tailored to the package: A build tool, called gnulib-tool, is provided that copies a tailored subset of Gnulib into the package.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In my opinion Gnulib is different here for now good reason.
There is no reason why Gnulib couldn't provide the same functionality, i.e. the portability wrapper and glue code functions
in a secure, reliable and structured way, as a normal shared library, like - say - &lt;a href="https://libbsd.freedesktop.org/"&gt;libbsd&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Even worse, this introduces several disadvantages:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Similar to all the generated build file cruft Autotools projects come with,
   Gnulib code from some arbitrary version dumped into a &lt;code&gt;lib/&lt;/code&gt; sub-directory is
   just another great opportunity for a &lt;a href="https://en.wikipedia.org/wiki/Supply_chain_attack"&gt;supply chain attacker&lt;/a&gt; to hide malicious code.&lt;/li&gt;
&lt;li&gt;As with static linking, and in contrast to shared linking, updates to library
   require rebuilding all users.&lt;/li&gt;
&lt;li&gt;Worse than with static linking, since the code is bundled, the dependency isn't obvious,
   and thus easy to miss. For example, it cannot be searched for with a distribution's package manager.&lt;/li&gt;
&lt;li&gt;Bundling Gnulib multiplies reviewing efforts, since with each copy it has to be checked
   whether it can be traced to the upstream Gnulib repository or contains malicious modifications.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Curiously, when it comes to &lt;a href="https://www.gnu.org/software/gnulib/manual/gnulib.html#Comparison-with-other-source-code-libraries"&gt;supply chain security Gnulib tries to talk down
other language package ecosystems&lt;/a&gt;, while completely ignoring it's own fundamental issues:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Many programming languages nowadays have
an ecosystem of reusable source code packages, available through a central site,
together with a tool that downloads dependencies from this central site. 
[.. Python example ..]
Most of them are vulnerable to supply chain attacks.
[..]
While some mitigations exist, they are often cumbersome to put in place.
[..]
Gnulib is not vulnerable to such attacks, because all of its code is managed in a single repository, with a limited set of committers and with established code review practices.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This misses the point very hard.&lt;/p&gt;
&lt;p&gt;If you take their Python example, the stuff Gnulib provides &lt;em&gt;is&lt;/em&gt; part of the Python standard library, since it &lt;em&gt;exactly&lt;/em&gt; fits Python's &lt;a href="https://en.wikipedia.org/wiki/Batteries_Included"&gt;batteries included&lt;/a&gt; philosophy.
Thus, there is really no need to install some random package via pip for basic functionality,
as the Gnulib team is trying to insinuate here.&lt;/p&gt;
&lt;p&gt;Having a limited set of comitters and 'established code review practices' transports almost zero information.
Many projects could claim that.
Even the &lt;a href="https://en.wikipedia.org/wiki/XZ_Utils_backdoor"&gt;xz project&lt;/a&gt; had a limited set of comitters.&lt;/p&gt;
&lt;p&gt;The main &lt;a href="https://en.wikipedia.org/wiki/Supply_chain_attack"&gt;supply chain&lt;/a&gt; risk the Gnulib team should worry about is the &lt;a href="https://en.wiktionary.org/wiki/vendor#Verb"&gt;vendoring&lt;/a&gt; of their 'library'.
Instead of encouraging developers to bundle their questionable
wrappers, where better standardized wrappers or common libraries
exist for decades, Gnulib could look into releasing a proper shared library.&lt;/p&gt;
&lt;h2 id="source-overhead"&gt;Source Overhead&lt;a class="headerlink" href="#source-overhead" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Another important metric is the size of the build system in a project.
The more files and more lines of code the higher the efforts for review, maintenance and debugging when something goes wrong.&lt;/p&gt;
&lt;p&gt;With Datamash 1.9 the &lt;a href="https://en.wikipedia.org/wiki/GNU_Autotools"&gt;Autotools&lt;/a&gt; build system is quite large.
There are at least:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;wc&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;aclocal.m4&lt;span class="w"&gt; &lt;/span&gt;cfg.mk&lt;span class="w"&gt; &lt;/span&gt;config.in&lt;span class="w"&gt;  &lt;/span&gt;configure&lt;span class="w"&gt;  &lt;/span&gt;configure.ac&lt;span class="w"&gt; &lt;/span&gt;GNUmakefile&lt;span class="w"&gt; &lt;/span&gt;init.cfg&lt;span class="w"&gt; &lt;/span&gt;maint.mk&lt;span class="w"&gt; &lt;/span&gt;Makefile.am&lt;span class="w"&gt; &lt;/span&gt;Makefile.in&lt;span class="w"&gt;    &lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;1926&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;aclocal.m4
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;193&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cfg.mk
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;3047&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;config.in
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;56440&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;configure
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;229&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;configure.ac
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;130&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;GNUmakefile
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="m"&gt;79&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;init.cfg
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;1950&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;maint.mk
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;347&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Makefile.am
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;12206&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Makefile.in
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;76547&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;total
$&lt;span class="w"&gt; &lt;/span&gt;du&lt;span class="w"&gt; &lt;/span&gt;-ch&lt;span class="w"&gt; &lt;/span&gt;aclocal.m4&lt;span class="w"&gt; &lt;/span&gt;cfg.mk&lt;span class="w"&gt; &lt;/span&gt;config.in&lt;span class="w"&gt;  &lt;/span&gt;configure&lt;span class="w"&gt;  &lt;/span&gt;configure.ac&lt;span class="w"&gt; &lt;/span&gt;GNUmakefile&lt;span class="w"&gt; &lt;/span&gt;init.cfg&lt;span class="w"&gt; &lt;/span&gt;maint.mk&lt;span class="w"&gt; &lt;/span&gt;Makefile.am&lt;span class="w"&gt; &lt;/span&gt;Makefile.in&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tail&lt;span class="w"&gt; &lt;/span&gt;-1
&lt;span class="m"&gt;2&lt;/span&gt;.5M&lt;span class="w"&gt;    &lt;/span&gt;total
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;configure&lt;/code&gt; is auto-generated from other files and part of the release source archive
to allow users compilation without having to install &lt;a href="https://en.wikipedia.org/wiki/Autoconf"&gt;autoconf&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After running &lt;code&gt;./configure&lt;/code&gt; another large Makefile is generated:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;wc&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;Makefile
&lt;span class="m"&gt;12206&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Makefile
$&lt;span class="w"&gt; &lt;/span&gt;du&lt;span class="w"&gt; &lt;/span&gt;-h&lt;span class="w"&gt; &lt;/span&gt;Makefile
800K&lt;span class="w"&gt;    &lt;/span&gt;Makefile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For comparison, the actual Datamash Source Code is less than 400 kilobytes large:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;du&lt;span class="w"&gt; &lt;/span&gt;-h&lt;span class="w"&gt; &lt;/span&gt;src
316K&lt;span class="w"&gt;    &lt;/span&gt;src
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In addition, the &lt;a href="https://en.wiktionary.org/wiki/vendor#Verb"&gt;vendored&lt;/a&gt; Gnulib sources come with over 30 thousand lines (or over 1 megabyte) of &lt;a href="https://en.wikipedia.org/wiki/M4_(computer_language)"&gt;m4&lt;/a&gt; macros and over 4 MiB of bundled C source code:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;wc&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;m4/*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tail&lt;span class="w"&gt; &lt;/span&gt;-1
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;33272&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;total
$&lt;span class="w"&gt; &lt;/span&gt;du&lt;span class="w"&gt; &lt;/span&gt;-h&lt;span class="w"&gt; &lt;/span&gt;m4
&lt;span class="m"&gt;1&lt;/span&gt;.7M&lt;span class="w"&gt;    &lt;/span&gt;m4
$&lt;span class="w"&gt; &lt;/span&gt;du&lt;span class="w"&gt; &lt;/span&gt;-h&lt;span class="w"&gt; &lt;/span&gt;lib
&lt;span class="m"&gt;4&lt;/span&gt;.3M&lt;span class="w"&gt;    &lt;/span&gt;lib
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When building from the datamash git repository, one also has to consider
at least just another largish shell script:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;wc&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;bootstrap*
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1087&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bootstrap
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;177&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bootstrap.conf
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1264&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;total
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is for generating Autotools files which aren't part of the repository,
such as the large &lt;code&gt;configure&lt;/code&gt; script.
It also updates the Gnulib bundle and downloads translation files.
Again this is another good target for a &lt;a href="https://en.wikipedia.org/wiki/Supply_chain_attack"&gt;supply chain attacker&lt;/a&gt; to hide malicious code.
Often such &lt;a href="https://en.wikipedia.org/wiki/Boilerplate_code"&gt;boilerplate code&lt;/a&gt; is just copy and pasted from some upstream and doesn't need to be customized,
but having to review that, having to check whether it was modified, if it was whether the modification is legitimate,
is quite wasteful, i.e. busy work that isn't necessary when using a better build tool.&lt;/p&gt;
&lt;p&gt;Having all those bits and pieces bundled also increases the risk only updating some of it and thus ending
up with a collection of moving parts and state that is very likely to be untested.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In comparison, with the Meson branch there is just:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;wc&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;meson.build&lt;span class="w"&gt; &lt;/span&gt;meson.options&lt;span class="w"&gt; &lt;/span&gt;po/meson.build&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;404&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;meson.build
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;meson.options
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;po/meson.build
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;415&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;total
$&lt;span class="w"&gt; &lt;/span&gt;du&lt;span class="w"&gt; &lt;/span&gt;-ch&lt;span class="w"&gt; &lt;/span&gt;meson.build&lt;span class="w"&gt; &lt;/span&gt;meson.options&lt;span class="w"&gt; &lt;/span&gt;po/meson.build&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tail&lt;span class="w"&gt; &lt;/span&gt;-1
28K&lt;span class="w"&gt;     &lt;/span&gt;total
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The 404 lines meson.build is structured like this:&lt;/p&gt;
&lt;table class="m-table"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#lines&lt;/th&gt;
&lt;th&gt;category&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;56&lt;/td&gt;
&lt;td&gt;comments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;55&lt;/td&gt;
&lt;td&gt;empty lines&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;91&lt;/td&gt;
&lt;td&gt;configuration data macro settings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;53&lt;/td&gt;
&lt;td&gt;test suite definitions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;149&lt;/td&gt;
&lt;td&gt;main build target definitions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;With Meson the megabytes of Autotools bloat listed above can be dropped.
Since the Meson build file uses a system-wide installed Gnulib, a few more megabytes can be dropped,
removing the bundled copy.
Removing those files would reduce the size of the release
&lt;code&gt;.tar.gz&lt;/code&gt; archive by almost 50 %, i.e. from 2.6 MiB to 1.4 MiB or
so.&lt;/p&gt;
&lt;h2 id="test-suite"&gt;Test Suite&lt;a class="headerlink" href="#test-suite" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.gnu.org/software/datamash/"&gt;Datamash&lt;/a&gt; comes with a test suite, i.e. a bunch of (mostly Perl) scripts that invoke the datamash
executables with various test inputs.&lt;/p&gt;
&lt;p&gt;With &lt;a href="https://en.wikipedia.org/wiki/GNU_Autotools"&gt;Autotools&lt;/a&gt; a test suite invocation runs like this:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;make&lt;span class="w"&gt; &lt;/span&gt;check
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;./.git&lt;span class="w"&gt;                               &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;--version&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;/dev/null&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;                                               &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;submodule&lt;span class="w"&gt; &lt;/span&gt;--quiet&lt;span class="w"&gt; &lt;/span&gt;foreach&lt;span class="w"&gt;                                 &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;test &amp;quot;$(git rev-parse &amp;quot;$sha1&amp;quot;)&amp;quot;                  \&lt;/span&gt;
&lt;span class="s1"&gt;          = &amp;quot;$(git merge-base origin &amp;quot;$sha1&amp;quot;)&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="se"&gt;\&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="o"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;maint.mk: found non-public submodule commit&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;                                             &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt;                                                            &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;                                                           &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
make&lt;span class="w"&gt;  &lt;/span&gt;check-recursive
make&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;Entering&lt;span class="w"&gt; &lt;/span&gt;directory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/home/juser/del/datamash-1.9&amp;#39;&lt;/span&gt;
Making&lt;span class="w"&gt; &lt;/span&gt;check&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;po
make&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;Entering&lt;span class="w"&gt; &lt;/span&gt;directory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/home/juser/del/datamash-1.9/po&amp;#39;&lt;/span&gt;
make&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;Nothing&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;be&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;check&amp;#39;&lt;/span&gt;.
make&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;Leaving&lt;span class="w"&gt; &lt;/span&gt;directory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/home/juser/del/datamash-1.9/po&amp;#39;&lt;/span&gt;
make&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;Entering&lt;span class="w"&gt; &lt;/span&gt;directory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/home/juser/del/datamash-1.9&amp;#39;&lt;/span&gt;
make&lt;span class="w"&gt;  &lt;/span&gt;check-TESTS
make&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;Entering&lt;span class="w"&gt; &lt;/span&gt;directory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/home/juser/del/datamash-1.9&amp;#39;&lt;/span&gt;
make&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;Entering&lt;span class="w"&gt; &lt;/span&gt;directory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/home/juser/del/datamash-1.9&amp;#39;&lt;/span&gt;
PASS:&lt;span class="w"&gt; &lt;/span&gt;tests/datamash-show-env.sh
PASS:&lt;span class="w"&gt; &lt;/span&gt;tests/datamash-tests.pl
PASS:&lt;span class="w"&gt; &lt;/span&gt;tests/datamash-tests-deprecated.pl
PASS:&lt;span class="w"&gt; &lt;/span&gt;tests/datamash-tests-2.pl
&lt;span class="o"&gt;[&lt;/span&gt;..&lt;span class="o"&gt;]&lt;/span&gt;
PASS:&lt;span class="w"&gt; &lt;/span&gt;tests/decorate-sort-tests.pl
&lt;span class="o"&gt;============================================================================&lt;/span&gt;
Testsuite&lt;span class="w"&gt; &lt;/span&gt;summary&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;GNU&lt;span class="w"&gt; &lt;/span&gt;datamash&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.9
&lt;span class="o"&gt;============================================================================&lt;/span&gt;
&lt;span class="c1"&gt;# TOTAL: 30&lt;/span&gt;
&lt;span class="c1"&gt;# PASS:  28&lt;/span&gt;
&lt;span class="c1"&gt;# SKIP:  2&lt;/span&gt;
&lt;span class="c1"&gt;# XFAIL: 0&lt;/span&gt;
&lt;span class="c1"&gt;# FAIL:  0&lt;/span&gt;
&lt;span class="c1"&gt;# XPASS: 0&lt;/span&gt;
&lt;span class="c1"&gt;# ERROR: 0&lt;/span&gt;
&lt;span class="o"&gt;============================================================================&lt;/span&gt;
make&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;Leaving&lt;span class="w"&gt; &lt;/span&gt;directory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/home/juser/del/datamash-1.9&amp;#39;&lt;/span&gt;
make&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;Leaving&lt;span class="w"&gt; &lt;/span&gt;directory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/home/juser/del/datamash-1.9&amp;#39;&lt;/span&gt;
make&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;Leaving&lt;span class="w"&gt; &lt;/span&gt;directory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/home/juser/del/datamash-1.9&amp;#39;&lt;/span&gt;
make&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;Leaving&lt;span class="w"&gt; &lt;/span&gt;directory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/home/juser/del/datamash-1.9&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As it's common with Autotools, there is a lot of extra noise and echoing that distracts from the important information.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In comparison the Meson output is more to the point and useful:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;meson&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt;                                                 &lt;/span&gt;
ninja:&lt;span class="w"&gt; &lt;/span&gt;Entering&lt;span class="w"&gt; &lt;/span&gt;directory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;/home/juser/del/datamash/build&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;
ninja:&lt;span class="w"&gt; &lt;/span&gt;no&lt;span class="w"&gt; &lt;/span&gt;work&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;.
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;/25&lt;span class="w"&gt; &lt;/span&gt;deprecated_test&lt;span class="w"&gt;                     &lt;/span&gt;OK&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.08s
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;/25&lt;span class="w"&gt; &lt;/span&gt;tests2&lt;span class="w"&gt;                              &lt;/span&gt;OK&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.40s
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;/25&lt;span class="w"&gt; &lt;/span&gt;deprecated2_test&lt;span class="w"&gt;                    &lt;/span&gt;OK&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.07s
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;/25&lt;span class="w"&gt; &lt;/span&gt;tests&lt;span class="w"&gt;                               &lt;/span&gt;OK&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.66s
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;/25&lt;span class="w"&gt; &lt;/span&gt;parser_test&lt;span class="w"&gt;                         &lt;/span&gt;OK&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.20s
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;/25&lt;span class="w"&gt; &lt;/span&gt;md5_test&lt;span class="w"&gt;                            &lt;/span&gt;OK&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.04s
&lt;span class="o"&gt;[&lt;/span&gt;..&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="m"&gt;25&lt;/span&gt;/25&lt;span class="w"&gt; &lt;/span&gt;deco_sort&lt;span class="w"&gt;                           &lt;/span&gt;OK&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.15s

Ok:&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="m"&gt;25&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;
Fail:&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;

Full&lt;span class="w"&gt; &lt;/span&gt;log&lt;span class="w"&gt; &lt;/span&gt;written&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;/home/juser/del/datamash/build/meson-logs/testlog.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id="side-effects"&gt;Side Effects&lt;a class="headerlink" href="#side-effects" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As a side effect of introducing &lt;a href="https://en.wikipedia.org/wiki/Meson_(software)"&gt;Meson&lt;/a&gt;, a few other things are now possible or much easier than with &lt;a href="https://en.wikipedia.org/wiki/GNU_Autotools"&gt;Autotools&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In particular, the first-class support of out-of-tree builds simplifies having multiple build trees around
for different target configurations, e.g. one with release optimization enabled, one with special debugging flags etc.&lt;/p&gt;
&lt;p&gt;Also, Meson supports out-of-the-box complicated build modes such as &lt;a href="https://en.wikipedia.org/wiki/Interprocedural_optimization"&gt;LTO&lt;/a&gt; and instrumentalization via
simple setup flags.&lt;/p&gt;
&lt;p&gt;Nowadays Autotools supports out-of-tree builds, as well, but usually this isn't documented well and for each project that uses Autotools  there is a risk that it doesn't support this mode fully. Similarly, passing LTO and instrumentalization flags is also possible with Autotools, but arguably this is more tedious and error-prone.&lt;/p&gt;
&lt;h2 id="see-also"&gt;See also&lt;a class="headerlink" href="#see-also" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My &lt;a href="https://opencommit.eu/gms/datamash/commits/branch/main"&gt;Meson branch&lt;/a&gt; (named &lt;code&gt;main&lt;/code&gt;) contains all the changes
that are discussed in this article. My changes are the first commits in 2026 and that series contains 9 consecutive commits or so.&lt;/p&gt;
&lt;p&gt;Direct links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://opencommit.eu/gms/datamash/src/branch/main/meson.build"&gt;main meson.build&lt;/a&gt; file&lt;/li&gt;
&lt;li&gt;&lt;a href="https://opencommit.eu/gms/datamash/src/branch/main/meson.options"&gt;meson.options&lt;/a&gt; - custom options that can be set when initializing the meson build directory&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;a class="headerlink" href="#conclusion" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Porting &lt;a href="https://www.gnu.org/software/datamash/"&gt;Datamash&lt;/a&gt; from &lt;a href="https://en.wikipedia.org/wiki/GNU_Autotools"&gt;Autotools&lt;/a&gt; to &lt;a href="https://en.wikipedia.org/wiki/Meson_(software)"&gt;Meson&lt;/a&gt; required relatively little effort
that quickly pays off, since build setup is sped up over ten times, build time is sped up two times
and the executable sizes are halved,
while the Meson build configuration is simpler and more compact and thus easier to review and maintain.&lt;/p&gt;
&lt;p&gt;It shows that Meson already was adopted by many open source projects,
because Meson support for configuration macros and tests is good.
Last but not least, it helps that Meson is better documented than Autotools.&lt;/p&gt;</content><category term="linux"></category><category term="meson"></category><category term="build"></category><category term="linux"></category></entry><entry><title>The curious case of nanosleep vs. hr_sleep</title><link href="https://gms.tf/hr_sleep.html" rel="alternate"></link><published>2024-07-09T19:00:00+02:00</published><updated>2024-07-09T19:00:00+02:00</updated><author><name>Georg Sauthoff</name></author><id>tag:gms.tf,2024-07-09:/hr_sleep.html</id><summary type="html">&lt;p&gt;This weekend, I finally got around reading a bookmarked paper that proposes an improved nanosleep:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.researchgate.net/publication/350371596_Metronome_adaptive_and_precise_intermittent_packet_retrieval_in_DPDK"&gt;Faltelli, Marco &amp;amp; Belocchi, Giacomo &amp;amp; Quaglia, Francesco &amp;amp; Pontarelli, Salvatore &amp;amp; Bianchi, Giuseppe. (2021). Metronome: adaptive and precise intermittent packet retrieval in DPDK.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the following I document a few notes.&lt;/p&gt;
&lt;h2 id="the-papers"&gt;The Papers&lt;a class="headerlink" href="#the-papers" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At page 4 I'm asking …&lt;/p&gt;</summary><content type="html">&lt;p&gt;This weekend, I finally got around reading a bookmarked paper that proposes an improved nanosleep:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.researchgate.net/publication/350371596_Metronome_adaptive_and_precise_intermittent_packet_retrieval_in_DPDK"&gt;Faltelli, Marco &amp;amp; Belocchi, Giacomo &amp;amp; Quaglia, Francesco &amp;amp; Pontarelli, Salvatore &amp;amp; Bianchi, Giuseppe. (2021). Metronome: adaptive and precise intermittent packet retrieval in DPDK.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the following I document a few notes.&lt;/p&gt;
&lt;h2 id="the-papers"&gt;The Papers&lt;a class="headerlink" href="#the-papers" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At page 4 I'm asking myself whether the authors ever posted their code to the LKML.
They did and the paper receives devastating criticism from &lt;a href="https://de.wikipedia.org/wiki/Thomas_Gleixner"&gt;Thomas
Gleixner&lt;/a&gt;, the Linux kernel
maintainer of the affected subsystem and a well-known expert in realtime computing in general and high resolution timers in particular:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lore.kernel.org/lkml/87eefl4s7f.ffs@nanos.tec.linutronix.de/"&gt;Thomas Gleixner. Re: [PATCH] kernel/time: Feedback reply for hr_sleep syscall, a fine-grained sleep service (2021-04-08)&lt;/a&gt;
(&lt;a href="https://lkml.org/lkml/2021/4/7/1614"&gt;mirror&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Turns out I was reading the &lt;a href="https://arxiv.org/abs/2103.13263v1"&gt;first version&lt;/a&gt; of a &lt;a href="https://arxiv.org/abs/2103.13263"&gt;preprint&lt;/a&gt;
and meanwhile &lt;a href="https://arxiv.org/pdf/2103.13263"&gt;version 3&lt;/a&gt; was released after that LKML post.
That version apparently corrects a few of the serious flaws pointed out by Thomas Gleixner, but:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the paper's authors don't reply on the LKML to the posted criticism&lt;/li&gt;
&lt;li&gt;they don't acknowledge Thomas Gleixner for his review in the acknowledgements
  section in the new version of their paper, although they certainly profited
  from his explanations and independent tests&lt;/li&gt;
&lt;li&gt;from the revised preprint (3rd version) the authors reference
  their old and identically named &lt;a href="https://dl.acm.org/doi/10.1145/3386367.3432730"&gt;conference paper&lt;/a&gt; for more
  details, although it also contains the criticized flaws that were
  removed from the 3rd preprint revision&lt;/li&gt;
&lt;li&gt;the ACM conference paper page doesn't mention any corrections&lt;/li&gt;
&lt;li&gt;the paper's accompanying &lt;a href="https://github.com/marcofaltelli/Metronome"&gt;github repository&lt;/a&gt; doesn't reference any of the criticism&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, in the 3rd preprint revision, as of 2024-07-09 the latest version, Section 3 A now has some new issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;'This factor can be controlled using the prctl() system call, putting it to the minimal value of 1.'&lt;br/&gt;
  Thus, the reader is left wondering what unit the minimal value might have ... (yes, it's nanoseconds).&lt;/li&gt;
&lt;li&gt;'These data have been collected by running the thread issuing
  the sleep request as a classical SCHED_OTHER (normal) priority
  thread and—as hinted before—with the timer slack of nanosleep()
  set to 1µs.'&lt;br/&gt;
  Either they mixed up the units and they actually used the minimal value of 1 ns or they used an unnecessarily high
  &lt;a href="https://manpath.be/f38/2/prctl#L1108"&gt;timer slack&lt;/a&gt; value to make their proposed improvement look a bit better.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-good"&gt;The Good&lt;a class="headerlink" href="#the-good" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Scrutinizing the API of syscalls that are parametrized with
timespec struct is certainly a valuable contribution.&lt;/p&gt;
&lt;p&gt;Passing a user pointer into a syscall that needs to be
dereferenced in the kernel (over the user space and kernel
address space boundary) has &lt;em&gt;some&lt;/em&gt;
&lt;a href="https://elixir.bootlin.com/linux/v6.9.8/source/kernel/time/time.c#L871"&gt;overhead&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also, such an indirection makes tracing it and debugging
somewhat harder.&lt;/p&gt;
&lt;p&gt;Looking at the &lt;a href="https://manpath.be/f39/2/nanosleep#L14"&gt;Linux sycall calling
conventions&lt;/a&gt;, it's clear
that there are more than enough call argument registers available
to pass all of struct timespec's fields directly via registers.
Also, in the case of nanosleep, which optionally returns the
remaining waiting time via a second argument pointer, at least some
architectures such as x86-64 would allow to return these values
via registers, as well. (on x86-64, syscall return values are put into
register rax and optionally register rdx which are both 64 bit
wide).&lt;/p&gt;
&lt;p&gt;Hence, it isn't even necessary to limit the sleep time
specification to a single nanoseconds argument like &lt;code&gt;hr_sleep()&lt;/code&gt; does.
FWIW, on 64 architectures, the Linux kernel has &lt;a href="https://elixir.bootlin.com/linux/v6.9.8/source/include/linux/ktime.h#L36"&gt;no problem to
convert&lt;/a&gt;
up to &lt;code&gt;2^63-1&lt;/code&gt; nanoseconds into its internal &lt;code&gt;ktime_t&lt;/code&gt; and for all
practical purposes a maximum sleep time of up to 292 years or so
seems to be sufficient.
Also FWIW, when using POSIX API such as &lt;code&gt;nanosleep()&lt;/code&gt; the valid
range of &lt;code&gt;timespec::tv_nsec&lt;/code&gt; is 'just' &lt;code&gt;[0, 999999999]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, measuring the likely tiny overhead of copying a timespec
struct from user to kernel space requires careful and rigorous
work.&lt;/p&gt;
&lt;p&gt;Of course, it's highly questionable whether eliminating the
expected timespec user to kernel copy overhead really would
justify adding another syscall.&lt;/p&gt;
&lt;h2 id="addendum"&gt;Addendum&lt;a class="headerlink" href="#addendum" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Apparently, the &lt;code&gt;hr_sleep()&lt;/code&gt; authors &lt;a href="https://lore.kernel.org/lkml/20210115180733.5663-1-marco.faltelli@uniroma2.it/"&gt;initially
contacted&lt;/a&gt; the
kernel community only after their &lt;a href="https://dl.acm.org/doi/10.1145/3386367.3432730"&gt;conference paper&lt;/a&gt; was published.
(i.e. first LKML post on 2021-01-15, conference paper was
published 2020-11-24 and presented at the conference in the first
week of December, 2020)
At that time it received some
&lt;a href="https://lore.kernel.org/lkml/CALCETrWfnL=3M3nmmHs-a3si5JptSCtF6cEtHVtsDNwA5mHnRg@mail.gmail.com/"&gt;feedback&lt;/a&gt; from another kernel
developer, Andy Lutomirski. Like with the second posting, the
hr_sleep authors didn't bother to reply directly to any of the
issues mentioned in the review.&lt;/p&gt;
&lt;p&gt;It seems that the paper was submitted to a proper conference and
hence it was peer reviewed, but perhaps the academic reviewers
weren't sufficiently familiar with the relevant parts of the
Linux kernel and thus missed the issues that were discussed on
the LKML.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;On 2024-07-07, I &lt;a href="https://github.com/marcofaltelli/Metronome/issues/5"&gt;opened an issue&lt;/a&gt; (&lt;a href="https://web.archive.org/web/20240707222020/https://github.com/marcofaltelli/Metronome/issues/5"&gt;archive&lt;/a&gt;) on the hr_sleep's github
&lt;a href="https://github.com/marcofaltelli/Metronome"&gt;repository&lt;/a&gt;, asking for clarification.&lt;/p&gt;
&lt;p&gt;It was deleted quickly without any comment:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This issue has been deleted.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For the sake of completeness I'm reproducing my github post below:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Clarifications nanosleep vs. hr_sleep measurements #5&lt;/p&gt;
&lt;p&gt;Reading through Section 3 A of your &lt;a href="https://arxiv.org/abs/2103.13263"&gt;preprint (3rd revision)&lt;/a&gt; I noticed a few issues:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;'This factor can be controlled using the prctl() system call, putting it to the minimal value of 1.'
    Perhaps you want to add the unit of that minimal value.&lt;/li&gt;
&lt;li&gt;'These data have been collected by running the thread issuing the sleep request as a classical SCHED_OTHER (normal) priority thread and—as hinted before—with the timer slack of nanosleep() set to 1µs.'
    Please clarify, did you really set the timer slack to 1 µs? Or did you set it to its minimal value, i.e. 1 &lt;em&gt;ns&lt;/em&gt;?&lt;/li&gt;
&lt;li&gt;'We remand the reader to [14] for an extended evaluation of this implementation.In [..]'
    Firstly, there is a space missing after the full stop.
    Secondly,  why do you continue to refer to an evaluation whose &lt;a href="https://lkml.org/lkml/2021/4/7/1614"&gt;flaws were pointed out to you by the maintainer of the relevant Linux subsystems&lt;/a&gt; while apparently you tried to address some of them in that 3rd version of your preprint?&lt;/li&gt;
&lt;li&gt;'Figure 1'
    You don't mention any details regarding the system you measured those latencies on.
    Thus, the results are hard to reproduce.
    The text states 'The tests have been conducted on an isolated NUMA node equipped with Intel Xeon Silver 2.1 GHz cores. The server is running Linux kernel 5.4.'
    But why don't you mention the exact CPU model and exact kernel version?
    Also relevant but completely missing: whether relevant kernel parameters where supplied, such as turning some/all kernel CPU bug mitigations off,  whether Hyperthreading was enabled, whether frequency scaling, energy saving modes, turbo boost, etc. etc. where enabled ...&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;BTW, google searches still return the &lt;a href="https://www.researchgate.net/publication/350371596_Metronome_adaptive_and_precise_intermittent_packet_retrieval_in_DPDK"&gt;ResearchGate page&lt;/a&gt; for the first preprint version at relatively high rank for me - perhaps you want to remove it from ResearchGate to avoid further confusion.&lt;/p&gt;
&lt;p&gt;Also, the &lt;a href="https://dl.acm.org/doi/10.1145/3386367.3432730"&gt;ACM page&lt;/a&gt; of the conference paper version doesn't contain any hints regarding regarding published corrections.&lt;/p&gt;
&lt;p&gt;Similarly, in the README of this repository you still link to your conference paper without mentioning that the analysis of hr_sleep vs. nanosleep therein is deeply flawed.&lt;/p&gt;
&lt;p&gt;Finally, since you profited from the LKML review of your paper and apparently that review prompted a significant rework of Section 3 A in the 3rd revision of your preprint, why didn't you acknowledge that Linux kernel maintainer in the Acknowledgement Section in your 3rd revision?&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="linux"></category><category term="kernel"></category><category term="time"></category><category term="dpdk"></category></entry><entry><title>On the Costs of Syscalls</title><link href="https://gms.tf/on-the-costs-of-syscalls.html" rel="alternate"></link><published>2021-08-30T15:00:00+02:00</published><updated>2021-08-30T15:00:00+02:00</updated><author><name>Georg Sauthoff</name></author><id>tag:gms.tf,2021-08-30:/on-the-costs-of-syscalls.html</id><summary type="html">&lt;p&gt;It's well known that &lt;a href="https://en.wikipedia.org/wiki/System_call"&gt;syscalls&lt;/a&gt; are expensive. And that
software mitigations against &lt;a href="https://en.wikipedia.org/wiki/Transient_execution_CPU_vulnerability"&gt;CPU bugs&lt;/a&gt; (such as Meltdown) even
have made them more expensive. But how expensive are they really?
To begin to answer this question I wrote a small
&lt;a href="https://github.com/gsauthof/osjitter/blob/master/bench_syscalls.cc"&gt;micro-benchmark&lt;/a&gt; in order to measure the minimal costs of a
syscall …&lt;/p&gt;</summary><content type="html">&lt;p&gt;It's well known that &lt;a href="https://en.wikipedia.org/wiki/System_call"&gt;syscalls&lt;/a&gt; are expensive. And that
software mitigations against &lt;a href="https://en.wikipedia.org/wiki/Transient_execution_CPU_vulnerability"&gt;CPU bugs&lt;/a&gt; (such as Meltdown) even
have made them more expensive. But how expensive are they really?
To begin to answer this question I wrote a small
&lt;a href="https://github.com/gsauthof/osjitter/blob/master/bench_syscalls.cc"&gt;micro-benchmark&lt;/a&gt; in order to measure the minimal costs of a
syscall. Meaning the cost of syscalls one always has to pay
whether a context-switch happens or not, even when the work in
the kernel is minuscule,  i.e. the costs of switching from
&lt;a href="https://en.wikipedia.org/wiki/Context_switch#User_and_kernel_mode_switching"&gt;user-mode to kernel-mode&lt;/a&gt; and back.&lt;/p&gt;
&lt;h2 id="methods"&gt;Methods&lt;a class="headerlink" href="#methods" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The user-kernel mode-switch &lt;a href="https://en.wikipedia.org/wiki/Benchmark_(computing)#Types_of_benchmark"&gt;micro-benchmark&lt;/a&gt; uses Google's
&lt;a href="https://github.com/google/benchmark"&gt;benchmark library&lt;/a&gt; for the measurements and is &lt;a href="https://github.com/gsauthof/osjitter/blob/master/bench_syscalls.cc"&gt;available in
a git repository&lt;/a&gt;. The repository also contains some helper
scripts, e.g. a &lt;a href="https://github.com/gsauthof/osjitter/blob/master/helper/bench_playbook.py"&gt;playbook&lt;/a&gt; for distributing it to and executing
it on a bunch of hosts. The benchmark library repeats each case
until the result is considered stable and the playbook allows for
repeated executions of the test cases. In the following sections
the median value of 100 repetitions is reported (real time in
nanoseconds).&lt;/p&gt;
&lt;p&gt;For the benchmark a bunch of syscalls is called that are expected
to be very cheap, such as getting the user id (UID), the program id
(PID), closing an invalid file descriptor, calling an
non-existent syscall etc. Thus, a measurement should really
just include two mode switches. As controls, a few cases don't call
a syscall but do other cheap stuff.&lt;/p&gt;
&lt;p&gt;I ran the benchmark on a heterogeneous set of hosts, i.e.
different kernels, operating systems and configurations. For more
details see also the Hosts Section.&lt;/p&gt;
&lt;h2 id="results-and-discussion"&gt;Results and Discussion&lt;a class="headerlink" href="#results-and-discussion" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The following table shows the real time (ns) for the different
cases:&lt;/p&gt;
&lt;style  type="text/css" &gt;
    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072 {
            margin-bottom: 1em
        }
&lt;/style&gt;
&lt;style  type="text/css" &gt;
    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col0 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col1 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col2 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col3 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col4 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col5 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col6 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col7 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col8 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col9 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col10 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col11 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col12 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col13 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col14 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col0 {
            background-color:  #ead4c8;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col1 {
            background-color:  #cdd9ec;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col2 {
            background-color:  #b40426;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col3 {
            background-color:  #aac7fd;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col4 {
            background-color:  #6f92f3;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col5 {
            background-color:  #6f92f3;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col6 {
            background-color:  #82a6fb;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col7 {
            background-color:  #4b64d5;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col8 {
            background-color:  #cdd9ec;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col9 {
            background-color:  #4b64d5;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col10 {
            background-color:  #f3c8b2;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col11 {
            background-color:  #4b64d5;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col12 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col13 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col14 {
            background-color:  #f3c8b2;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col0 {
            background-color:  #e3d9d3;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col1 {
            background-color:  #d6dce4;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col2 {
            background-color:  #b40426;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col3 {
            background-color:  #6c8ff1;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col4 {
            background-color:  #6c8ff1;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col5 {
            background-color:  #6c8ff1;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col6 {
            background-color:  #7ea1fa;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col7 {
            background-color:  #4a63d3;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col8 {
            background-color:  #c6d6f1;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col9 {
            background-color:  #5a78e4;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col10 {
            background-color:  #efcfbf;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col11 {
            background-color:  #4a63d3;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col12 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col13 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col14 {
            background-color:  #efcfbf;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col0 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col1 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col2 {
            background-color:  #3e51c5;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col3 {
            background-color:  #f7ac8e;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col4 {
            background-color:  #f7aa8c;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col5 {
            background-color:  #cdd9ec;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col6 {
            background-color:  #f39778;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col7 {
            background-color:  #c6d6f1;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col8 {
            background-color:  #b40426;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col9 {
            background-color:  #e16751;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col10 {
            background-color:  #e9d5cb;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col11 {
            background-color:  #adc9fd;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col12 {
            background-color:  #6485ec;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col13 {
            background-color:  #b3cdfb;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col14 {
            background-color:  #92b4fe;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col0 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col1 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col2 {
            background-color:  #3e51c5;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col3 {
            background-color:  #f7ac8e;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col4 {
            background-color:  #f7a98b;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col5 {
            background-color:  #cedaeb;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col6 {
            background-color:  #f39475;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col7 {
            background-color:  #c6d6f1;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col8 {
            background-color:  #b40426;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col9 {
            background-color:  #e16751;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col10 {
            background-color:  #e9d5cb;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col11 {
            background-color:  #adc9fd;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col12 {
            background-color:  #6485ec;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col13 {
            background-color:  #b5cdfa;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col14 {
            background-color:  #93b5fe;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col0 {
            background-color:  #e9785d;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col1 {
            background-color:  #9dbdff;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col2 {
            background-color:  #a5c3fe;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col3 {
            background-color:  #f7b396;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col4 {
            background-color:  #f7ad90;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col5 {
            background-color:  #a9c6fd;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col6 {
            background-color:  #f5a081;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col7 {
            background-color:  #a5c3fe;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col8 {
            background-color:  #b40426;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col9 {
            background-color:  #d65244;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col10 {
            background-color:  #d2dbe8;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col11 {
            background-color:  #90b2fe;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col12 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col13 {
            background-color:  #9abbff;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col14 {
            background-color:  #5673e0;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col0 {
            background-color:  #b40426;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col1 {
            background-color:  #d2dbe8;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col2 {
            background-color:  #d1dae9;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col3 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col4 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col5 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col6 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col7 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col8 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col9 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col10 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col11 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col12 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col13 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col14 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col0 {
            background-color:  #e46e56;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col1 {
            background-color:  #93b5fe;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col2 {
            background-color:  #a5c3fe;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col3 {
            background-color:  #f7b497;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col4 {
            background-color:  #f7af91;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col5 {
            background-color:  #aec9fc;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col6 {
            background-color:  #f49a7b;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col7 {
            background-color:  #a5c3fe;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col8 {
            background-color:  #b40426;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col9 {
            background-color:  #d65244;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col10 {
            background-color:  #d5dbe5;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col11 {
            background-color:  #8fb1fe;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col12 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col13 {
            background-color:  #98b9ff;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col14 {
            background-color:  #5a78e4;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col0 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col1 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col2 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col3 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col4 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col5 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col6 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col7 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col8 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col9 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col10 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col11 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col12 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col13 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col14 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col0 {
            background-color:  #4f69d9;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col1 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col2 {
            background-color:  #93b5fe;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col3 {
            background-color:  #ee8468;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col4 {
            background-color:  #f5a081;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col5 {
            background-color:  #f7b89c;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col6 {
            background-color:  #ee8468;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col7 {
            background-color:  #f2cbb7;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col8 {
            background-color:  #e0654f;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col9 {
            background-color:  #e5d8d1;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col10 {
            background-color:  #b40426;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col11 {
            background-color:  #e5d8d1;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col12 {
            background-color:  #e5d8d1;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col13 {
            background-color:  #e5d8d1;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col14 {
            background-color:  #b40426;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col0 {
            background-color:  #d75445;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col1 {
            background-color:  #bbd1f8;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col2 {
            background-color:  #d5dbe5;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col3 {
            background-color:  #f7b194;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col4 {
            background-color:  #f7b79b;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col5 {
            background-color:  #cdd9ec;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col6 {
            background-color:  #f08a6c;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col7 {
            background-color:  #adc9fd;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col8 {
            background-color:  #b40426;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col9 {
            background-color:  #dd5f4b;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col10 {
            background-color:  #dedcdb;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col11 {
            background-color:  #88abfd;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col12 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col13 {
            background-color:  #93b5fe;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col14 {
            background-color:  #6e90f2;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col0 {
            background-color:  #b2ccfb;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col1 {
            background-color:  #506bda;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col2 {
            background-color:  #b40426;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col3 {
            background-color:  #80a3fa;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col4 {
            background-color:  #80a3fa;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col5 {
            background-color:  #80a3fa;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col6 {
            background-color:  #80a3fa;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col7 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col8 {
            background-color:  #c9d7f0;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col9 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col10 {
            background-color:  #6788ee;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col11 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col12 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col13 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col14 {
            background-color:  #6788ee;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col0 {
            background-color:  #6b8df0;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col1 {
            background-color:  #6b8df0;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col2 {
            background-color:  #b40426;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col3 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col4 {
            background-color:  #516ddb;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col5 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col6 {
            background-color:  #516ddb;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col7 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col8 {
            background-color:  #516ddb;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col9 {
            background-color:  #516ddb;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col10 {
            background-color:  #86a9fc;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col11 {
            background-color:  #516ddb;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col12 {
            background-color:  #516ddb;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col13 {
            background-color:  #516ddb;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col14 {
            background-color:  #86a9fc;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col0 {
            background-color:  #d95847;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col1 {
            background-color:  #a6c4fe;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col2 {
            background-color:  #aec9fc;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col3 {
            background-color:  #f7b79b;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col4 {
            background-color:  #f7aa8c;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col5 {
            background-color:  #b1cbfc;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col6 {
            background-color:  #f18f71;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col7 {
            background-color:  #a1c0ff;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col8 {
            background-color:  #b40426;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col9 {
            background-color:  #cf453c;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col10 {
            background-color:  #dbdcde;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col11 {
            background-color:  #93b5fe;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col12 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col13 {
            background-color:  #9abbff;
            color:  #000000;
        }    #T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col14 {
            background-color:  #5d7ce6;
            color:  #000000;
        }&lt;/style&gt;
&lt;table id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072" &gt;&lt;thead&gt;    &lt;tr&gt;        &lt;th class="index_name level0" &gt;host&lt;/th&gt;        &lt;th class="col_heading level0 col0" &gt;5i4250u&lt;/th&gt;        &lt;th class="col_heading level0 col1" &gt;7i6600u&lt;/th&gt;        &lt;th class="col_heading level0 col2" &gt;ac3758&lt;/th&gt;        &lt;th class="col_heading level0 col3" &gt;x2643&lt;/th&gt;        &lt;th class="col_heading level0 col4" &gt;x2667h&lt;/th&gt;        &lt;th class="col_heading level0 col5" &gt;x2667s&lt;/th&gt;        &lt;th class="col_heading level0 col6" &gt;x2687w&lt;/th&gt;        &lt;th class="col_heading level0 col7" &gt;x2689&lt;/th&gt;        &lt;th class="col_heading level0 col8" &gt;x2690&lt;/th&gt;        &lt;th class="col_heading level0 col9" &gt;xg6144&lt;/th&gt;        &lt;th class="col_heading level0 col10" &gt;xg6148&lt;/th&gt;        &lt;th class="col_heading level0 col11" &gt;xg6246&lt;/th&gt;        &lt;th class="col_heading level0 col12" &gt;xg6256&lt;/th&gt;        &lt;th class="col_heading level0 col13" &gt;xg6256b&lt;/th&gt;        &lt;th class="col_heading level0 col14" &gt;xs4110&lt;/th&gt;    &lt;/tr&gt;    &lt;tr&gt;        &lt;th class="index_name level0" &gt;name&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;    &lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
                &lt;tr&gt;
                        &lt;th id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072level0_row0" class="row_heading level0 row0" &gt;assign&lt;/th&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col0" class="data row0 col0" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col1" class="data row0 col1" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col2" class="data row0 col2" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col3" class="data row0 col3" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col4" class="data row0 col4" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col5" class="data row0 col5" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col6" class="data row0 col6" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col7" class="data row0 col7" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col8" class="data row0 col8" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col9" class="data row0 col9" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col10" class="data row0 col10" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col11" class="data row0 col11" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col12" class="data row0 col12" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col13" class="data row0 col13" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row0_col14" class="data row0 col14" &gt;0&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                        &lt;th id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072level0_row1" class="row_heading level0 row1" &gt;clock_gettime&lt;/th&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col0" class="data row1 col0" &gt;23&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col1" class="data row1 col1" &gt;21&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col2" class="data row1 col2" &gt;31&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col3" class="data row1 col3" &gt;19&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col4" class="data row1 col4" &gt;16&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col5" class="data row1 col5" &gt;16&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col6" class="data row1 col6" &gt;17&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col7" class="data row1 col7" &gt;14&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col8" class="data row1 col8" &gt;21&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col9" class="data row1 col9" &gt;14&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col10" class="data row1 col10" &gt;24&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col11" class="data row1 col11" &gt;14&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col12" class="data row1 col12" &gt;13&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col13" class="data row1 col13" &gt;13&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row1_col14" class="data row1 col14" &gt;24&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                        &lt;th id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072level0_row2" class="row_heading level0 row2" &gt;clock_gettime_mono&lt;/th&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col0" class="data row2 col0" &gt;23&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col1" class="data row2 col1" &gt;22&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col2" class="data row2 col2" &gt;32&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col3" class="data row2 col3" &gt;16&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col4" class="data row2 col4" &gt;16&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col5" class="data row2 col5" &gt;16&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col6" class="data row2 col6" &gt;17&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col7" class="data row2 col7" &gt;14&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col8" class="data row2 col8" &gt;21&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col9" class="data row2 col9" &gt;15&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col10" class="data row2 col10" &gt;24&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col11" class="data row2 col11" &gt;14&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col12" class="data row2 col12" &gt;13&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col13" class="data row2 col13" &gt;13&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row2_col14" class="data row2 col14" &gt;24&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                        &lt;th id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072level0_row3" class="row_heading level0 row3" &gt;clock_gettime_mono_raw&lt;/th&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col0" class="data row3 col0" &gt;23&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col1" class="data row3 col1" &gt;22&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col2" class="data row3 col2" &gt;33&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col3" class="data row3 col3" &gt;542&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col4" class="data row3 col4" &gt;544&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col5" class="data row3 col5" &gt;350&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col6" class="data row3 col6" &gt;582&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col7" class="data row3 col7" &gt;332&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col8" class="data row3 col8" &gt;762&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col9" class="data row3 col9" &gt;660&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col10" class="data row3 col10" &gt;427&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col11" class="data row3 col11" &gt;274&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col12" class="data row3 col12" &gt;122&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col13" class="data row3 col13" &gt;290&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row3_col14" class="data row3 col14" &gt;218&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                        &lt;th id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072level0_row4" class="row_heading level0 row4" &gt;clock_gettime_tai&lt;/th&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col0" class="data row4 col0" &gt;23&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col1" class="data row4 col1" &gt;21&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col2" class="data row4 col2" &gt;32&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col3" class="data row4 col3" &gt;542&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col4" class="data row4 col4" &gt;546&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col5" class="data row4 col5" &gt;352&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col6" class="data row4 col6" &gt;587&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col7" class="data row4 col7" &gt;333&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col8" class="data row4 col8" &gt;762&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col9" class="data row4 col9" &gt;660&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col10" class="data row4 col10" &gt;427&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col11" class="data row4 col11" &gt;274&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col12" class="data row4 col12" &gt;122&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col13" class="data row4 col13" &gt;292&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row4_col14" class="data row4 col14" &gt;218&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                        &lt;th id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072level0_row5" class="row_heading level0 row5" &gt;close&lt;/th&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col0" class="data row5 col0" &gt;568&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col1" class="data row5 col1" &gt;262&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col2" class="data row5 col2" &gt;275&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col3" class="data row5 col3" &gt;484&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col4" class="data row5 col4" &gt;495&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col5" class="data row5 col5" &gt;283&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col6" class="data row5 col6" &gt;514&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col7" class="data row5 col7" &gt;277&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col8" class="data row5 col8" &gt;668&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col9" class="data row5 col9" &gt;610&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col10" class="data row5 col10" &gt;356&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col11" class="data row5 col11" &gt;243&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col12" class="data row5 col12" &gt;93&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col13" class="data row5 col13" &gt;257&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row5_col14" class="data row5 col14" &gt;145&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                        &lt;th id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072level0_row6" class="row_heading level0 row6" &gt;getpid&lt;/th&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col0" class="data row6 col0" &gt;558&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col1" class="data row6 col1" &gt;257&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col2" class="data row6 col2" &gt;255&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col3" class="data row6 col3" &gt;2&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col4" class="data row6 col4" &gt;1&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col5" class="data row6 col5" &gt;1&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col6" class="data row6 col6" &gt;2&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col7" class="data row6 col7" &gt;1&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col8" class="data row6 col8" &gt;2&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col9" class="data row6 col9" &gt;1&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col10" class="data row6 col10" &gt;2&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col11" class="data row6 col11" &gt;1&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col12" class="data row6 col12" &gt;1&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col13" class="data row6 col13" &gt;1&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row6_col14" class="data row6 col14" &gt;2&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                        &lt;th id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072level0_row7" class="row_heading level0 row7" &gt;getuid&lt;/th&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col0" class="data row7 col0" &gt;560&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col1" class="data row7 col1" &gt;231&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col2" class="data row7 col2" &gt;259&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col3" class="data row7 col3" &gt;464&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col4" class="data row7 col4" &gt;473&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col5" class="data row7 col5" &gt;276&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col6" class="data row7 col6" &gt;505&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col7" class="data row7 col7" &gt;259&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col8" class="data row7 col8" &gt;649&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col9" class="data row7 col9" &gt;592&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col10" class="data row7 col10" &gt;347&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col11" class="data row7 col11" &gt;224&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col12" class="data row7 col12" &gt;78&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col13" class="data row7 col13" &gt;239&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row7_col14" class="data row7 col14" &gt;137&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                        &lt;th id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072level0_row8" class="row_heading level0 row8" &gt;nothing&lt;/th&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col0" class="data row8 col0" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col1" class="data row8 col1" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col2" class="data row8 col2" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col3" class="data row8 col3" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col4" class="data row8 col4" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col5" class="data row8 col5" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col6" class="data row8 col6" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col7" class="data row8 col7" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col8" class="data row8 col8" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col9" class="data row8 col9" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col10" class="data row8 col10" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col11" class="data row8 col11" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col12" class="data row8 col12" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col13" class="data row8 col13" &gt;0&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row8_col14" class="data row8 col14" &gt;0&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                        &lt;th id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072level0_row9" class="row_heading level0 row9" &gt;pthread_cond_signal&lt;/th&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col0" class="data row9 col0" &gt;3&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col1" class="data row9 col1" &gt;2&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col2" class="data row9 col2" &gt;6&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col3" class="data row9 col3" &gt;14&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col4" class="data row9 col4" &gt;13&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col5" class="data row9 col5" &gt;12&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col6" class="data row9 col6" &gt;14&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col7" class="data row9 col7" &gt;11&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col8" class="data row9 col8" &gt;15&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col9" class="data row9 col9" &gt;10&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col10" class="data row9 col10" &gt;17&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col11" class="data row9 col11" &gt;10&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col12" class="data row9 col12" &gt;10&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col13" class="data row9 col13" &gt;10&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row9_col14" class="data row9 col14" &gt;17&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                        &lt;th id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072level0_row10" class="row_heading level0 row10" &gt;sched_yield&lt;/th&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col0" class="data row10 col0" &gt;706&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col1" class="data row10 col1" &gt;374&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col2" class="data row10 col2" &gt;430&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col3" class="data row10 col3" &gt;569&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col4" class="data row10 col4" &gt;560&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col5" class="data row10 col5" &gt;414&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col6" class="data row10 col6" &gt;634&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col7" class="data row10 col7" &gt;346&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col8" class="data row10 col8" &gt;773&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col9" class="data row10 col9" &gt;694&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col10" class="data row10 col10" &gt;454&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col11" class="data row10 col11" &gt;280&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col12" class="data row10 col12" &gt;126&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col13" class="data row10 col13" &gt;300&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row10_col14" class="data row10 col14" &gt;232&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                        &lt;th id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072level0_row11" class="row_heading level0 row11" &gt;sqrt&lt;/th&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col0" class="data row11 col0" &gt;6&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col1" class="data row11 col1" &gt;2&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col2" class="data row11 col2" &gt;15&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col3" class="data row11 col3" &gt;4&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col4" class="data row11 col4" &gt;4&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col5" class="data row11 col5" &gt;4&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col6" class="data row11 col6" &gt;4&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col7" class="data row11 col7" &gt;1&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col8" class="data row11 col8" &gt;7&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col9" class="data row11 col9" &gt;1&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col10" class="data row11 col10" &gt;3&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col11" class="data row11 col11" &gt;1&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col12" class="data row11 col12" &gt;1&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col13" class="data row11 col13" &gt;1&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row11_col14" class="data row11 col14" &gt;3&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                        &lt;th id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072level0_row12" class="row_heading level0 row12" &gt;sqrtrec&lt;/th&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col0" class="data row12 col0" &gt;4&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col1" class="data row12 col1" &gt;4&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col2" class="data row12 col2" &gt;15&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col3" class="data row12 col3" &gt;2&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col4" class="data row12 col4" &gt;3&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col5" class="data row12 col5" &gt;2&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col6" class="data row12 col6" &gt;3&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col7" class="data row12 col7" &gt;2&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col8" class="data row12 col8" &gt;3&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col9" class="data row12 col9" &gt;3&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col10" class="data row12 col10" &gt;5&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col11" class="data row12 col11" &gt;3&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col12" class="data row12 col12" &gt;3&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col13" class="data row12 col13" &gt;3&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row12_col14" class="data row12 col14" &gt;5&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                        &lt;th id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072level0_row13" class="row_heading level0 row13" &gt;syscall&lt;/th&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col0" class="data row13 col0" &gt;560&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col1" class="data row13 col1" &gt;252&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col2" class="data row13 col2" &gt;265&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col3" class="data row13 col3" &gt;440&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col4" class="data row13 col4" &gt;460&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col5" class="data row13 col5" &gt;269&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col6" class="data row13 col6" &gt;497&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col7" class="data row13 col7" &gt;243&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col8" class="data row13 col8" &gt;620&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col9" class="data row13 col9" &gt;579&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col10" class="data row13 col10" &gt;345&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col11" class="data row13 col11" &gt;221&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col12" class="data row13 col12" &gt;76&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col13" class="data row13 col13" &gt;233&lt;/td&gt;
                        &lt;td id="T_dde6e7fa_0989_11ec_9e32_f8cab850d072row13_col14" class="data row13 col14" &gt;136&lt;/td&gt;
            &lt;/tr&gt;
    &lt;/tbody&gt;&lt;/table&gt;

&lt;h3 id="controls"&gt;Controls&lt;a class="headerlink" href="#controls" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The cases used as controls are 'nothing' which literally does
nothing, 'assign' which just assigns to a variable, &lt;code&gt;sqrt&lt;/code&gt; which
computes the square root of a small constant and &lt;code&gt;sqrtrec&lt;/code&gt; which
stacks a bunch of sqrt calls. The results for these are
plausible, i.e. doing nothing is really measured as &lt;code&gt;10**-7&lt;/code&gt; ns or
so, the assignment costs 0.5 ns or so and computing the square
root takes only a few ns. Perhaps the most remarkable result is,
that computing the square root on a Atom CPU (ac3758) is pretty
constant over the 2 cases, whereas on the other hosts its runtime
depends on its argument.&lt;/p&gt;
&lt;h3 id="clock-gettime"&gt;Clock Gettime&lt;a class="headerlink" href="#clock-gettime" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Looking at the syscalls, one relation that holds true on all
hosts is that the &lt;code&gt;clock_gettime(CLOCK_REALTIME)&lt;/code&gt; syscall is much
faster than &lt;code&gt;getuid()&lt;/code&gt; or &lt;code&gt;close()&lt;/code&gt;. This can be explained by the
fact that on Linux, &lt;code&gt;clock_gettime(CLOCK_REALTIME)&lt;/code&gt; and a &lt;a href="https://manpath.be/f34/7/vdso#L334"&gt;few
other syscalls&lt;/a&gt; are implemented via the efficient &lt;a href="https://en.wikipedia.org/wiki/VDSO"&gt;vDSO&lt;/a&gt; mechanism.
Meaning when they are called no mode switch happens!&lt;/p&gt;
&lt;p&gt;&lt;code&gt;clock_gettime()&lt;/code&gt; supports different clocks and not all of them
are vDSO optimized on all kernels. The table shows that on RHEL 7 querying
&lt;code&gt;CLOCK_MONOTIC_RAW&lt;/code&gt; and &lt;code&gt;CLOCK_TAI&lt;/code&gt; invokes a real syscall while
on Fedora 33 kernels (5.12/5.13) these clock readings are also
implemented as vDSO.&lt;/p&gt;
&lt;h3 id="dummy-signaling"&gt;Dummy Signaling&lt;a class="headerlink" href="#dummy-signaling" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Similarly, the dummy &lt;code&gt;pthread_cond_signal()&lt;/code&gt; case, which signals
without anybody listening, is much cheaper than a real syscall - 
since the C library doesn't have to call a real syscall but can
just invoke some relatively cheap atomic operation.&lt;/p&gt;
&lt;h3 id="getpid"&gt;Getpid&lt;a class="headerlink" href="#getpid" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;getpid()&lt;/code&gt; syscall is surprisingly fast on RHEL 7. It turns
out that RHEL 7 ships an &lt;a href="https://manpath.be/f34/2/getpid#L43"&gt;older glibc version which caches the ID
of a process&lt;/a&gt;! Which arguably is a curious optimization, since,
what's the point? I mean how often to you have to call
&lt;code&gt;getpid()&lt;/code&gt; in a program, really? At some point (around Fedora 26)
this &lt;a href="https://bugzilla.redhat.com/show_bug.cgi?id=1469670"&gt;feature was removed&lt;/a&gt; since it apparently caused more
&lt;a href="https://yarchive.net/comp/linux/getpid_caching.html"&gt;trouble&lt;/a&gt; than it's worth. Perhaps unsurprisingly, that
&lt;a href="https://bugzilla.redhat.com/show_bug.cgi?id=1469670"&gt;removal&lt;/a&gt; even &lt;a href="https://xkcd.com/1172/"&gt;broke somebodies workflow&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="real-syscalls"&gt;Real Syscalls&lt;a class="headerlink" href="#real-syscalls" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;So looking at the real syscalls, the user-kernel mode switches
cost in the order of a few hundred nanoseconds, on all hosts. The
higher costs on some hosts can be explained by CPU bug
mitigations being enabled (they are enabled by default) and/or
kind of older/lower-end hardware. See also the Hosts Section for
some details.&lt;/p&gt;
&lt;p&gt;The fastest host is &lt;code&gt;xg6256&lt;/code&gt; which manages to switch modes in
less than 100 ns. It has a fast CPU with good
single core performance (Xeon Gold 6256), has frequency scaling
disabled and runs at a constant 4.1 GHz frequency above it's base
frequency (i.e. a frequency between the base and turbo
frequency).&lt;/p&gt;
&lt;h3 id="sched-yield"&gt;Sched Yield&lt;a class="headerlink" href="#sched-yield" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;sched_yield()&lt;/code&gt; syscall could be considered as a minimal work
syscall, e.g. when there is nothing to yield to. Also, the
benchmark process is running under the standard scheduling policy
and on Linux &lt;a href="https://manpath.be/f34/2/sched_yield#L43"&gt;&lt;code&gt;sched_yield()&lt;/code&gt; is described as&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;sched_yield()&lt;/code&gt; is  intended for use with real-time scheduling policies (i.e., &lt;code&gt;SCHED_FIFO&lt;/code&gt; or &lt;code&gt;SCHED_RR&lt;/code&gt;).
Use of &lt;code&gt;sched_yield()&lt;/code&gt; with nondeterministic scheduling policies such as &lt;code&gt;SCHED_OTHER&lt;/code&gt; is unspecified  and
very likely means your application design is broken.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So unspecified could mean that the syscall just bails out after
the process' scheduling policy compares equal to &lt;code&gt;SCHED_OTHER&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;On most hosts sched_yield 150 ns or so more expensive than a
really minimal syscall such as &lt;code&gt;getuid()&lt;/code&gt; - which indicates some
more overhead, but not necessarily a context switch.&lt;/p&gt;
&lt;h3 id="nanosleep"&gt;Nanosleep&lt;a class="headerlink" href="#nanosleep" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A bit out of the competition is the &lt;code&gt;nanosleep()&lt;/code&gt; syscall:&lt;/p&gt;
&lt;style  type="text/css" &gt;
    #T_07822f0e_0988_11ec_9e32_f8cab850d072 {
            margin-bottom: 1em
        }
&lt;/style&gt;
&lt;style  type="text/css" &gt;
    #T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col0 {
            background-color:  #e7d7ce;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col1 {
            background-color:  #5875e1;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col2 {
            background-color:  #e6d7cf;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col3 {
            background-color:  #5f7fe8;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col4 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col5 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col6 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col7 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col8 {
            background-color:  #4e68d8;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col9 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col10 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col11 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col12 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col13 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col14 {
            background-color:  #b40426;
            color:  #f1f1f1;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col0 {
            background-color:  #d4dbe6;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col1 {
            background-color:  #7093f3;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col2 {
            background-color:  #b40426;
            color:  #f1f1f1;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col3 {
            background-color:  #8caffe;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col4 {
            background-color:  #6a8bef;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col5 {
            background-color:  #5977e3;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col6 {
            background-color:  #7093f3;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col7 {
            background-color:  #bad0f8;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col8 {
            background-color:  #97b8ff;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col9 {
            background-color:  #6b8df0;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col10 {
            background-color:  #7295f4;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col11 {
            background-color:  #5673e0;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col12 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col13 {
            background-color:  #4a63d3;
            color:  #f1f1f1;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col14 {
            background-color:  #b5cdfa;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col0 {
            background-color:  #d3dbe7;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col1 {
            background-color:  #7093f3;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col2 {
            background-color:  #b40426;
            color:  #f1f1f1;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col3 {
            background-color:  #8caffe;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col4 {
            background-color:  #6a8bef;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col5 {
            background-color:  #5977e3;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col6 {
            background-color:  #6f92f3;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col7 {
            background-color:  #b9d0f9;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col8 {
            background-color:  #97b8ff;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col9 {
            background-color:  #6b8df0;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col10 {
            background-color:  #7295f4;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col11 {
            background-color:  #5673e0;
            color:  #000000;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col12 {
            background-color:  #3b4cc0;
            color:  #f1f1f1;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col13 {
            background-color:  #4a63d3;
            color:  #f1f1f1;
        }    #T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col14 {
            background-color:  #b3cdfb;
            color:  #000000;
        }&lt;/style&gt;
&lt;table id="T_07822f0e_0988_11ec_9e32_f8cab850d072"&gt;&lt;thead&gt;    &lt;tr&gt;        &lt;th class="index_name level0" &gt;host&lt;/th&gt;        &lt;th class="col_heading level0 col0" &gt;5i4250u&lt;/th&gt;        &lt;th class="col_heading level0 col1" &gt;7i6600u&lt;/th&gt;        &lt;th class="col_heading level0 col2" &gt;ac3758&lt;/th&gt;        &lt;th class="col_heading level0 col3" &gt;x2643&lt;/th&gt;        &lt;th class="col_heading level0 col4" &gt;x2667h&lt;/th&gt;        &lt;th class="col_heading level0 col5" &gt;x2667s&lt;/th&gt;        &lt;th class="col_heading level0 col6" &gt;x2687w&lt;/th&gt;        &lt;th class="col_heading level0 col7" &gt;x2689&lt;/th&gt;        &lt;th class="col_heading level0 col8" &gt;x2690&lt;/th&gt;        &lt;th class="col_heading level0 col9" &gt;xg6144&lt;/th&gt;        &lt;th class="col_heading level0 col10" &gt;xg6148&lt;/th&gt;        &lt;th class="col_heading level0 col11" &gt;xg6246&lt;/th&gt;        &lt;th class="col_heading level0 col12" &gt;xg6256&lt;/th&gt;        &lt;th class="col_heading level0 col13" &gt;xg6256b&lt;/th&gt;        &lt;th class="col_heading level0 col14" &gt;xs4110&lt;/th&gt;    &lt;/tr&gt;    &lt;tr&gt;        &lt;th class="index_name level0" &gt;name&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;        &lt;th class="blank" &gt;&lt;/th&gt;    &lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
                &lt;tr&gt;
                        &lt;th id="T_07822f0e_0988_11ec_9e32_f8cab850d072level0_row0" class="row_heading level0 row0" &gt;nanosleep0&lt;/th&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col0" class="data row0 col0" &gt;52632&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col1" class="data row0 col1" &gt;50474&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col2" class="data row0 col2" &gt;52620&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col3" class="data row0 col3" &gt;50588&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col4" class="data row0 col4" &gt;50003&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col5" class="data row0 col5" &gt;50011&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col6" class="data row0 col6" &gt;50000&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col7" class="data row0 col7" &gt;50014&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col8" class="data row0 col8" &gt;50312&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col9" class="data row0 col9" &gt;50018&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col10" class="data row0 col10" &gt;50000&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col11" class="data row0 col11" &gt;50014&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col12" class="data row0 col12" &gt;50000&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col13" class="data row0 col13" &gt;50000&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row0_col14" class="data row0 col14" &gt;54866&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                        &lt;th id="T_07822f0e_0988_11ec_9e32_f8cab850d072level0_row1" class="row_heading level0 row1" &gt;nanosleep0_slack1&lt;/th&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col0" class="data row1 col0" &gt;4355&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col1" class="data row1 col1" &gt;2836&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col2" class="data row1 col2" &gt;7076&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col3" class="data row1 col3" &gt;3247&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col4" class="data row1 col4" &gt;2736&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col5" class="data row1 col5" &gt;2483&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col6" class="data row1 col6" &gt;2835&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col7" class="data row1 col7" &gt;3908&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col8" class="data row1 col8" &gt;3401&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col9" class="data row1 col9" &gt;2762&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col10" class="data row1 col10" &gt;2870&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col11" class="data row1 col11" &gt;2446&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col12" class="data row1 col12" &gt;1974&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col13" class="data row1 col13" &gt;2248&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row1_col14" class="data row1 col14" &gt;3837&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                        &lt;th id="T_07822f0e_0988_11ec_9e32_f8cab850d072level0_row2" class="row_heading level0 row2" &gt;nanosleep1_slack1&lt;/th&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col0" class="data row2 col0" &gt;4348&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col1" class="data row2 col1" &gt;2840&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col2" class="data row2 col2" &gt;7102&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col3" class="data row2 col3" &gt;3252&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col4" class="data row2 col4" &gt;2736&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col5" class="data row2 col5" &gt;2486&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col6" class="data row2 col6" &gt;2834&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col7" class="data row2 col7" &gt;3908&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col8" class="data row2 col8" &gt;3410&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col9" class="data row2 col9" &gt;2767&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col10" class="data row2 col10" &gt;2871&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col11" class="data row2 col11" &gt;2446&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col12" class="data row2 col12" &gt;1975&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col13" class="data row2 col13" &gt;2246&lt;/td&gt;
                        &lt;td id="T_07822f0e_0988_11ec_9e32_f8cab850d072row2_col14" class="data row2 col14" &gt;3836&lt;/td&gt;
            &lt;/tr&gt;
    &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Calling &lt;code&gt;nanosleep()&lt;/code&gt; to sleep for 0 ns or 1 ns seemingly also is
a very cheap syscall or even a null operation.&lt;/p&gt;
&lt;p&gt;However, in the first case it takes 50 µs an all hosts.
Incidentally, 50 µs is also the &lt;a href="https://manpath.be/f34/2/prctl#L1052"&gt;default timer slack value&lt;/a&gt;
for a normally scheduled process on Linux. The &lt;a href="https://lwn.net/Articles/588086/"&gt;timer slack
mechanism&lt;/a&gt; extends timer expirations up to the slack value in
order to group multiple timers since this reduces wake ups and
thus saves energy. And since &lt;code&gt;nanosleep()&lt;/code&gt; creates a timer, it's
also affected by this mechanism.&lt;/p&gt;
&lt;p&gt;Thus, the other nanosleep cases &lt;a href="https://github.com/gsauthof/osjitter/blob/f1a4ca9cbf7516efc61c3bab2fe06ffe83cfb43c/bench_syscalls.cc#L117"&gt;set a minimal timer slack&lt;/a&gt; of 1
ns which reduces the runtime, as expected. However, it's still
much more expensive than the other syscalls. Of course, a timer
expiration has a limited accuracy. However, with 0 ns or 1 ns no
timer has to be expired, really. It turns out that calling
&lt;code&gt;nanosleep()&lt;/code&gt; unconditionally yields a (voluntary) &lt;a href="https://en.wikipedia.org/wiki/Context_switch"&gt;context
switch&lt;/a&gt;.  Even on isolated cores, where the scheduler happily
switches to the swapper kernel thread. Thus, the last two
nanonsleep cases really measure the context switch costs which
are more expensive than a simple mode switch.&lt;/p&gt;
&lt;p&gt;The costs of a context switch match what &lt;a href="https://eli.thegreenplace.net/2018/measuring-context-switching-and-memory-overheads-for-linux-threads/#how-expensive-are-context-switches"&gt;others are
measuring&lt;/a&gt; (modulo division by two).&lt;/p&gt;
&lt;h2 id="hosts"&gt;Hosts&lt;a class="headerlink" href="#hosts" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The following table shows the hosts under benchmark:&lt;/p&gt;
&lt;table class="m-table"&gt;
  &lt;thead&gt;
    &lt;tr style="text-align: right;"&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;host&lt;/th&gt;
      &lt;th&gt;CPU&lt;/th&gt;
      &lt;th&gt;mitigations&lt;/th&gt;
      &lt;th&gt;poll&lt;/th&gt;
      &lt;th&gt;os&lt;/th&gt;
      &lt;th&gt;kernel&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;td&gt;5i4250u&lt;/td&gt;
      &lt;td&gt;Core i5-4250U&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;Fedora 33&lt;/td&gt;
      &lt;td&gt;5.12&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;7i6600u&lt;/td&gt;
      &lt;td&gt;Core i7-6600U&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;Fedora 33&lt;/td&gt;
      &lt;td&gt;5.13&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;td&gt;ac3758&lt;/td&gt;
      &lt;td&gt;Atom C3758&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;Fedora 33&lt;/td&gt;
      &lt;td&gt;5.13&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;td&gt;x2643&lt;/td&gt;
      &lt;td&gt;Xeon E5-2643 v2&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;RHEL 7&lt;/td&gt;
      &lt;td&gt;3.10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;4&lt;/th&gt;
      &lt;td&gt;x2667h&lt;/td&gt;
      &lt;td&gt;Xeon E5-2667 v3&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;RHEL 7&lt;/td&gt;
      &lt;td&gt;3.10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;5&lt;/th&gt;
      &lt;td&gt;x2667s&lt;/td&gt;
      &lt;td&gt;Xeon E5-2667 v3&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;RHEL 7&lt;/td&gt;
      &lt;td&gt;3.10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;6&lt;/th&gt;
      &lt;td&gt;x2687w&lt;/td&gt;
      &lt;td&gt;Xeon E5-2687W v3&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;RHEL 7&lt;/td&gt;
      &lt;td&gt;3.10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;7&lt;/th&gt;
      &lt;td&gt;x2689&lt;/td&gt;
      &lt;td&gt;Xeon E5-2689 v4&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;RHEL 7&lt;/td&gt;
      &lt;td&gt;3.10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;8&lt;/th&gt;
      &lt;td&gt;x2690&lt;/td&gt;
      &lt;td&gt;Xeon E5-2690 0&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;RHEL 7&lt;/td&gt;
      &lt;td&gt;3.10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;9&lt;/th&gt;
      &lt;td&gt;xg6144&lt;/td&gt;
      &lt;td&gt;Xeon Gold 6144&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;RHEL 7&lt;/td&gt;
      &lt;td&gt;3.10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;10&lt;/th&gt;
      &lt;td&gt;xg6148&lt;/td&gt;
      &lt;td&gt;Xeon Gold 6148&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;RHEL 7&lt;/td&gt;
      &lt;td&gt;3.10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;11&lt;/th&gt;
      &lt;td&gt;xg6246&lt;/td&gt;
      &lt;td&gt;Xeon Gold 6246&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;RHEL 7&lt;/td&gt;
      &lt;td&gt;3.10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;12&lt;/th&gt;
      &lt;td&gt;xg6256&lt;/td&gt;
      &lt;td&gt;Xeon Gold 6256&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;RHEL 7&lt;/td&gt;
      &lt;td&gt;3.10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;13&lt;/th&gt;
      &lt;td&gt;xg6256b&lt;/td&gt;
      &lt;td&gt;Xeon Gold 6256&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;RHEL 7&lt;/td&gt;
      &lt;td&gt;3.10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;14&lt;/th&gt;
      &lt;td&gt;xs4110&lt;/td&gt;
      &lt;td&gt;Xeon Silver 4110&lt;/td&gt;
      &lt;td&gt;no&lt;/td&gt;
      &lt;td&gt;yes&lt;/td&gt;
      &lt;td&gt;RHEL 7&lt;/td&gt;
      &lt;td&gt;3.10&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the kernels are the ones packaged by the distributions&lt;/li&gt;
&lt;li&gt;most RHEL hosts are on RHEL 7.9&lt;/li&gt;
&lt;li&gt;CPU mitigations are disabled via the &lt;code&gt;mitigations=off&lt;/code&gt; kernel
  parameter or similar parameters&lt;/li&gt;
&lt;li&gt;polling means that CPU frequency scaling and power saving is
  disabled via kernel parameters and tuned PM QoS settings&lt;/li&gt;
&lt;li&gt;so the host's CPU runs on a fixed frequency; where possible this
  frequency is set slightly above the base frequency, e.g. on the
  Xeon Gold 6256 CPU it's set to 4.1 GHz&lt;/li&gt;
&lt;li&gt;the Atom CPU doesn't support Hyperthreading and Hyperthreading
  is disabled on all Xeon hosts&lt;/li&gt;
&lt;li&gt;all hosts have SELinux and/or Auditing enabled (on Fedora/RHEL these features are enabled by default) which adds some syscall overhead to some degree&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="terminology"&gt;Terminology&lt;a class="headerlink" href="#terminology" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are basically two important separate terms to distinguish
in the above discussion:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Context_switch#User_and_kernel_mode_switching"&gt;Mode Switch&lt;/a&gt; (or Mode Transition)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Context_switch"&gt;Context Switch&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The definitions of these terms might vary in different literature
and different operating systems. Also, in other contexts (no pun
intended!) one might describe different modes as different
contexts. However, the definitions given in the linked Wikipedia
articles are widely used and apply to Linux.&lt;/p&gt;
&lt;p&gt;Basically, a mode transition denotes the switch between user mode and
kernel mode (or between user space and kernel space) whereas a context switch
denotes a switch between different tasks, which is facilitated by
the kernel. A context switch requires more work than a mode
switch and thus is more expensive.&lt;/p&gt;</content><category term="linux"></category><category term="kernel"></category><category term="linux"></category><category term="latency"></category></entry><entry><title>The Rise of Meson</title><link href="https://gms.tf/the-rise-of-meson.html" rel="alternate"></link><published>2021-08-07T13:00:00+02:00</published><updated>2021-08-07T13:00:00+02:00</updated><author><name>Georg Sauthoff</name></author><id>tag:gms.tf,2021-08-07:/the-rise-of-meson.html</id><summary type="html">&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Meson_(software)#Adopters"&gt;More and more&lt;/a&gt; open source projects seem to switch to the &lt;a href="https://mesonbuild.com/"&gt;Meson&lt;/a&gt; build tool, in the last years.
In an attempt to quantify this development I looked at the build tools usage by &lt;a href="https://en.wikipedia.org/wiki/Fedora_(operating_system)"&gt;Fedora&lt;/a&gt; packages, during the last 14 years.&lt;/p&gt;
&lt;h2 id="about-meson"&gt;About Meson&lt;a class="headerlink" href="#about-meson" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Meson_(software)"&gt;Meson&lt;/a&gt; is a build tool with good C …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Meson_(software)#Adopters"&gt;More and more&lt;/a&gt; open source projects seem to switch to the &lt;a href="https://mesonbuild.com/"&gt;Meson&lt;/a&gt; build tool, in the last years.
In an attempt to quantify this development I looked at the build tools usage by &lt;a href="https://en.wikipedia.org/wiki/Fedora_(operating_system)"&gt;Fedora&lt;/a&gt; packages, during the last 14 years.&lt;/p&gt;
&lt;h2 id="about-meson"&gt;About Meson&lt;a class="headerlink" href="#about-meson" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Meson_(software)"&gt;Meson&lt;/a&gt; is a build tool with good C/C++ support. It's
written in Python and generates &lt;a href="https://en.wikipedia.org/wiki/Ninja_(build_system)"&gt;Ninja&lt;/a&gt; build files. Since it was
created after &lt;a href="https://en.wikipedia.org/wiki/CMake"&gt;CMake&lt;/a&gt; (which was initially released in
2000), it had the chance to learn from CMake's
mistakes. In comparison to CMake, Meson has better &lt;a href="https://mesonbuild.com/Manual.html"&gt;documentation&lt;/a&gt;,
it doesn't support generating classic makefiles, it only supports
out of source tree builds, and its domain specific language is
arguably much better designed.&lt;/p&gt;
&lt;p&gt;So, from the start, Meson arguably is also more opinionated in its
design, but in a useful way. Usually, simple stuff is easy to solve
with Meson and there is one kind of obvious way to do it. Whereas
with CMake, there are often several ways to implement common
build tasks (cf. &lt;a href="https://en.wikipedia.org/wiki/There%27s_more_than_one_way_to_do_it"&gt;TMTOWTDI&lt;/a&gt;), including some legacy ones. With Meson, build files
are often much shorter than equivalent CMake ones.&lt;/p&gt;
&lt;p&gt;CMake evolved over the years and it's possible to write -
say - a modern style of CMake build files that are less awful,
and use it in a modern way to some degree, but it feels
that the &lt;a href="https://cmake.org/cmake/help/v3.21/"&gt;official documentation&lt;/a&gt; doesn't help much in that regard,
and that one would have to &lt;a href="https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/"&gt;study&lt;/a&gt; several &lt;a href="https://cliutils.gitlab.io/modern-cmake/#other-sources"&gt;books&lt;/a&gt; on modern CMake in
order to arrive there.&lt;/p&gt;
&lt;h2 id="fedora-data"&gt;Fedora Data&lt;a class="headerlink" href="#fedora-data" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The first packages that required Meson to build arrived in Fedora 22,
i.e. 6 years ago (in 2015, Fedora runs on a half-year release schedule and
Meson was initially released in 2013, 8 years ago).
Since then the number of packages that
build-require Meson grew to almost 600 hundred:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://gms.tf/image/meson-et-al-fedora.svg" alt="Number of packages that build-require CMake, Meson, Scons" width="100%"/&gt;&lt;/p&gt;
&lt;p&gt;So this graph shows the number of packages that require a notable
build tool at build time, for each Fedora release.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/SCons"&gt;Scons&lt;/a&gt; never really took off and nowadays only a handful of
packages still require it. In contrast, the Meson usage shows
some serious growth.&lt;/p&gt;
&lt;p&gt;When looking at the Meson growth in relation to the packages that
either require CMake, Scons or Meson - Meson is now required by
30 % or so of the packages:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://gms.tf/image/meson-rise.svg" alt="Relative Meson Build Requirements growth" width="100%"/&gt;&lt;/p&gt;
&lt;p&gt;The growth slowed a bit down in the last Fedora releases, it
seems.&lt;/p&gt;
&lt;h2 id="other-tools"&gt;Other Tools&lt;a class="headerlink" href="#other-tools" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So what about &lt;a href="https://en.wikipedia.org/wiki/Autoconf"&gt;Autoconf&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Automake"&gt;Automake&lt;/a&gt;, etc.
(a.k.a. &lt;a href="https://en.wikipedia.org/wiki/GNU_Autotools"&gt;Autotools&lt;/a&gt;) and other build tools?
Since most project that use Autotools release their tar archive
files with already generated configure scripts/make files, the
resulting packages don't depend on those tools. Plus, &lt;a href="https://fedoraproject.org/wiki/Changes/Remove_make_from_BuildRoot"&gt;before
Fedora 34&lt;/a&gt;, there isn't even a dependency on GNU make,
since it was part of the standard build root environment. This
changed with Fedora 34, where 9000 packages or so depend on GNU
make.  Subtracting the packages that also require CMake, there
remain 8000 packages or so that might use Autotools. But how many
of those use plain old Makefiles can't be easily derived by just
looking at the package dependencies.&lt;/p&gt;
&lt;p&gt;In any case, using Autotools for a modern C/C++ project in 2021
is like using CVS for source code version control in 2021: there
are better tools available and thus it isn't very interesting to
still consider the legacy solutions.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Boost_(C%2B%2B_libraries)"&gt;Boost&lt;/a&gt; project has its own build system: &lt;a href="https://en.wikipedia.org/wiki/Perforce_Jam#Boost.Jam"&gt;BJam&lt;/a&gt;. There
is some &lt;a href="https://www.boost.org/build/doc/html/index.html"&gt;documentation&lt;/a&gt;, but it's kind of minimal and
cryptic. As of Fedora 34, the is no package that build-requires
BJam. (Boost itself doesn't need to explicitly require it since
it's included in the Boost release tar archive.) Incidentally,
the Boost steering committee &lt;a href="https://lists.boost.org/boost-interest/2017/07/0162.php"&gt;announced&lt;/a&gt; in 2017 its
desire to migrate to CMake, however, as of 2021, the current
Boost documentation still just mentions BJam/b2 for building
Boost.&lt;/p&gt;
&lt;h2 id="methods"&gt;Methods&lt;a class="headerlink" href="#methods" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The build tool usage stats were obtained with:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;fedora_release,tool,users&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;meson&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cmake&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;scons&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;=$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dnf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;repoquery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;releasever&lt;/span&gt;&lt;span class="o"&gt;=$&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;disablerepo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;*&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;enablerepo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;*-source&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;                      &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;arch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;whatrequires&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;k&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="n"&gt;sed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s/-[0-9]:[0-9].*$//&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &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="n"&gt;sort&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;u&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="n"&gt;wc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;$i,$k,$n&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt;
&lt;span class="p"&gt;}&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="n"&gt;tee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;stat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And for GNU make, on Fedora 34:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;dnf repoquery --disablerepo=&amp;#39;*&amp;#39; --enablerepo=&amp;#39;*-source&amp;#39; --arch=src \
      --whatrequires make | sed &amp;#39;s/-[0-9]:[0-9].*$//&amp;#39; \
    | sort -u  | wc -l &amp;gt; f34-require-make.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content><category term="linux"></category><category term="meson"></category><category term="build"></category><category term="linux"></category></entry><entry><title>Deploying Full Disk Encryption in the Cloud with Ansible</title><link href="https://gms.tf/fedora-initramfs.html" rel="alternate"></link><published>2020-11-17T12:00:00+01:00</published><updated>2020-11-17T12:00:00+01:00</updated><author><name>Georg Sauthoff</name></author><id>tag:gms.tf,2020-11-17:/fedora-initramfs.html</id><summary type="html">&lt;p&gt;Deploying a new virtual machine 'in the cloud' is simple enough
and fast. As long as one doesn't need to setup an encrypted root
filesystem. This article shows how to automate the setup of a
Fedora system with an encrypted root filesystem remotely - 'in
the cloud' - on e.g. a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Deploying a new virtual machine 'in the cloud' is simple enough
and fast. As long as one doesn't need to setup an encrypted root
filesystem. This article shows how to automate the setup of a
Fedora system with an encrypted root filesystem remotely - 'in
the cloud' - on e.g. a DigitalOcean, Hetzner, Linode, etc. VM -
with Ansible and a special &lt;a href="https://github.com/gsauthof/playbook/tree/master/fedora/initramfs"&gt;Fedora rescue system&lt;/a&gt; that runs purely
from an &lt;a href="https://en.wikipedia.org/wiki/Initial_ramdisk"&gt;initramfs&lt;/a&gt; archive.&lt;/p&gt;
&lt;h2 id="motivation"&gt;Motivation&lt;a class="headerlink" href="#motivation" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Having an encrypted root filesystem gives you &lt;a href="https://en.wikipedia.org/wiki/Data_at_rest"&gt;data at rest
protection&lt;/a&gt;. At the end of the day, your virtual disk
device inside your virtual machine (VM) is just a file on a
storage solution where disks are getting replaced and reallocated
for other things. After - say - hardware replacements perhaps
such a disk even ends up on eBay without being properly deleted
and thus some random person now has access to your data. With
your root filesystem being encrypted you are protected against
such scenarios.&lt;/p&gt;
&lt;p&gt;If you think that such a scenario is far fetched, see also for
example &lt;a href="https://www.heise.de/ct/artikel/SSD-mit-Daten-von-Jugendamt-und-Zulassungsstelle-bei-eBay-gefunden-4615144.html"&gt;this 2019 computer magazine article (in German)&lt;/a&gt;
which describes in detail how some SSDs with very sensitive
personal data ended up on eBay.&lt;/p&gt;
&lt;h2 id="the-problem"&gt;The Problem&lt;a class="headerlink" href="#the-problem" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Cloud providers such as DigitalOcean, Linode or Hetzner provide a
set of pre-built disk images for different operating systems.
Users also have the option to add custom images to their account,
usually. When deploying a new virtual machine (e.g. a Droplet
when using DigitalOcean) the selected disk image is extracted to
the new VM guest, the image has to run some first-boot
initialization script which fetches the network configuration,
creates sshd host keys and stuff like that.&lt;/p&gt;
&lt;p&gt;This process is very fast because the image is pre-built and just
needs to be copied while the first-boot initialization doesn't
have much to do. Compare this with a traditional automated Linux
install method such as &lt;a href="https://en.wikipedia.org/wiki/Kickstart_(Linux)"&gt;Kickstart&lt;/a&gt; where RPMs are installed one
after the other. This takes much longer.&lt;/p&gt;
&lt;p&gt;The disadvantage is a loss in flexibility. Especially, this makes
setting up the root filesystem on a &lt;a href="https://en.wikipedia.org/wiki/Linux_Unified_Key_Setup"&gt;LUKS encrypted&lt;/a&gt; device
challenging.&lt;/p&gt;
&lt;h2 id="non-solutions"&gt;Non-Solutions&lt;a class="headerlink" href="#non-solutions" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A naive approach to a remote system with an encrypted root
filesystem is to locally install a Linux distribution with disk
encryption enabled and upload the resulting image. The problem
with this is that if you want to deploy multiple VMs all then
have the same LUKS encryption key. Certainly you can't openly
share this image with others and you would upload a new image for
each new VM deployment. Obviously this is tedious and doesn't
scale.&lt;/p&gt;
&lt;p&gt;After the VM is deployed with an unencrypted root filesystem,
encrypting it on the fly isn't possible, because the root
filesystem is in use.&lt;/p&gt;
&lt;h2 id="a-solution"&gt;A Solution&lt;a class="headerlink" href="#a-solution" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For some time Linux has the interesting feature to boot a new
kernel image from a running Linux system. That means the
currently running kernel can be replaced with a new one using the
&lt;a href="https://en.wikipedia.org/wiki/Kexec"&gt;kexec system call&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A standard part of the Linux boot process is to extract an early
boot root filesystem &lt;a href="https://en.wikipedia.org/wiki/Initial_ramdisk"&gt;image into a ram disk&lt;/a&gt;, execute an init
process from it that basically mounts the real root filesystem
and switches to it. Of course, the final root filesystem switch
is optional.&lt;/p&gt;
&lt;p&gt;In combination these features, i.e. kexec and an early-boot
environment, can be used to &lt;a href="https://en.wikipedia.org/wiki/Bootstrapping"&gt;bootstrap&lt;/a&gt; a fresh Linux installation
from scratch - from a running system.&lt;/p&gt;
&lt;p&gt;The basic idea here is to kexec a new kernel with an
&lt;a href="https://en.wikipedia.org/wiki/Initial_ramdisk"&gt;initramfs&lt;/a&gt; image that contains a small Linux system, i.e.
one that includes enough software to provide network connectivity
including SSH and to drive the Fedora install process.&lt;/p&gt;
&lt;p&gt;Recently, I implemented this approach, i.e. I thus wrote a
&lt;a href="https://github.com/gsauthof/playbook/tree/master/fedora/initramfs"&gt;script that creates such initramfs images&lt;/a&gt;. That means it
installs a minimal Fedora system into an initramfs.&lt;/p&gt;
&lt;p&gt;I also created an &lt;a href="https://github.com/gsauthof/playbook/tree/master/fedora/initramfs/ansible"&gt;Ansible playbook that drives the whole
process&lt;/a&gt;.  That means it downloads the initramfs image to the VM,
creates VM specific configuration, kexecs into the rescue system
and finally installs the &lt;a href="https://en.wikipedia.org/wiki/Linux_Unified_Key_Setup"&gt;LUKS-encrypted&lt;/a&gt; target system from there.
It even supports creating a DigitalOcean Droplet, first.&lt;/p&gt;
&lt;p&gt;Without considering the VM creation, the playbook consists of 30
steps or so. After the playbook finishes, the target VM has an
encrypted root filesystem with a fresh Fedora system on top of
it.&lt;/p&gt;
&lt;p&gt;So far, I successfully used this method and playbook on
DigitalOcean, Linode and Hetzner VMs and even on some old-school
bare-metal root-server (rented from Manitu).&lt;/p&gt;</content><category term="linux"></category><category term="initramfs"></category><category term="ansible"></category><category term="fedora"></category></entry><entry><title>Deploying SSH Host Keys with Digital Ocean Droplets</title><link href="https://gms.tf/ssh-host-key-deployment.html" rel="alternate"></link><published>2020-06-05T22:00:00+02:00</published><updated>2020-06-05T22:00:00+02:00</updated><author><name>Georg Sauthoff</name></author><id>tag:gms.tf,2020-06-05:/ssh-host-key-deployment.html</id><summary type="html">&lt;p&gt;When deploying a VM in a remote location one might end up in an
impossible situation: a VM base image doesn't contain &lt;a href="https://en.wikipedia.org/wiki/Secure_Shell"&gt;SSH&lt;/a&gt;
host keys as otherwise the image couldn't be shared between
multiple hosts. But if SSH host keys are auto-generated during
the first boot one doesn't know their …&lt;/p&gt;</summary><content type="html">&lt;p&gt;When deploying a VM in a remote location one might end up in an
impossible situation: a VM base image doesn't contain &lt;a href="https://en.wikipedia.org/wiki/Secure_Shell"&gt;SSH&lt;/a&gt;
host keys as otherwise the image couldn't be shared between
multiple hosts. But if SSH host keys are auto-generated during
the first boot one doesn't know their fingerprints and thus they
can't be trusted on first connect. This article describes how to
securely deploy SSH host keys when deploying a Digital Ocean
Droplet (i.e. a VM).&lt;/p&gt;
&lt;h2 id="problem-description"&gt;Problem Description&lt;a class="headerlink" href="#problem-description" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Pre-build disk images usually don't contain any SSH host keys. At
least they shouldn't contain any host keys if they are used for
multiple hosts, but sometimes people get this wrong, e.g.
&lt;a href="https://wiki.hetzner.de/index.php/Ed25519/en#Security_Notice_for_Ed25519_SSH_host_keys"&gt;Hetzner (a web hoster) in 2015&lt;/a&gt;, &lt;a href="https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20150625-ironport"&gt;Cisco (a network equipment
company) also in 2015&lt;/a&gt; and &lt;a href="https://blog.shodan.io/duplicate-ssh-keys-everywhere/"&gt;many others&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One common approach is to generate the SSH host keys during first
boot.&lt;/p&gt;
&lt;p&gt;The problem is then: how can we trust this new machine during the
first SSH login? We don't know the fingerprint of any SSH host
key because they are newly generated, remotely. Thus, we can't
really trust it that way.&lt;/p&gt;
&lt;p&gt;One approach is to just accept any first encountered host key and
store its fingerprint for later verifications (&lt;a href="https://en.wikipedia.org/wiki/Trust_on_first_use"&gt;trust on first
use&lt;/a&gt;). This is better then &lt;a href="https://github.com/devopsgroup-io/vagrant-digitalocean/issues/289"&gt;ignoring&lt;/a&gt; the problem
completely but this still makes you vulnerable against
&lt;a href="https://en.wikipedia.org/wiki/Man-in-the-middle_attack"&gt;man-in-the-middle attacks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Generating a new disk image with new host keys for each new host
and transferring it to a cloud provider doesn't scale.&lt;/p&gt;
&lt;h2 id="a-solution-for-digital-ocean-droplets"&gt;A Solution for Digital Ocean Droplets&lt;a class="headerlink" href="#a-solution-for-digital-ocean-droplets" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;DigitalOcean (like some other cloud providers) uses
&lt;a href="https://cloudinit.readthedocs.io/en/latest/"&gt;cloud-init&lt;/a&gt; for the first-boot configuration. And cloud-init
also supports supplying SSH host keys via the so called
&lt;a href="https://cloudinit.readthedocs.io/en/20.2/topics/format.html#cloud-config-data"&gt;cloud-config&lt;/a&gt;. Thus, we can supply a cloud-config (with
locally generated host keys) via the &lt;a href="https://developers.digitalocean.com/documentation/v2/#create-a-new-droplet"&gt;user-data parameter&lt;/a&gt;
when creating a new VM via the DigitalOcean API.&lt;/p&gt;
&lt;p&gt;SSH host key problem solved. Almost, since it turns out that the
user-data cloud-config is served over a &lt;a href="https://developers.digitalocean.com/documentation/metadata/"&gt;link-local address&lt;/a&gt;
for the lifetime of the VM. Since this turns the SSH host keys
into world-readable information (to processes running on that VM)
we have to consider these cloud-init SSH host keys as ephemeral
and have to replace them with another set (of locally generated
SSH host keys) as part of our deployment.&lt;/p&gt;
&lt;p&gt;See also an example Ansible playbook of mine that &lt;a href="https://github.com/gsauthof/playbook/blob/1a792ae163276b5f831225ac61c95f6b131d9c01/fedora/initramfs/ansible/digital-ocean.yml#L15"&gt;creates a
DigitalOcean Droplet&lt;/a&gt; and &lt;a href="https://github.com/gsauthof/playbook/blob/master/fedora/initramfs/ansible/digital-ocean.yml#L109"&gt;automates the SSH host key
deployment&lt;/a&gt; in the described way.&lt;/p&gt;
&lt;p&gt;In that way, &lt;a href="https://en.wikipedia.org/wiki/Man-in-the-middle_attack"&gt;man-in-the-middle attacks&lt;/a&gt; can be successfully
averted (and detected) during deployment as the DigitalOcean API
is called over HTTPS (where the server's certificate is signed by
a trusted CA) and the first ephemeral SSH host key is thus
transferred over that secure connection. The second and final SSH
host key is transferred over SSH where the (ephemeral) host key
can be authenticated by it's known fingerprint.&lt;/p&gt;</content><category term="linux"></category><category term="ansible"></category><category term="digitalocean"></category><category term="ssh"></category></entry><entry><title>NFS VM Cached Read Illustrated</title><link href="https://gms.tf/nfs-vm-cached-read-illustrated.html" rel="alternate"></link><published>2017-08-12T18:12:00+02:00</published><updated>2017-08-12T18:12:00+02:00</updated><author><name>Georg Sauthoff</name></author><id>tag:gms.tf,2017-08-12:/nfs-vm-cached-read-illustrated.html</id><summary type="html">&lt;p&gt;This article illustrates how the &lt;a href="https://en.wikipedia.org/wiki/Virtual_memory"&gt;virtual memory (VM)&lt;/a&gt; subsystem of
the &lt;a href="https://en.wikipedia.org/wiki/Linux"&gt;Linux kernel&lt;/a&gt; is able to cache files that are located on
an &lt;a href="https://en.wikipedia.org/wiki/Network_File_System"&gt;NFS&lt;/a&gt; server.&lt;/p&gt;
&lt;div class="toc"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#environment"&gt;Environment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#high-level-view"&gt;High-Level View&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#dstat"&gt;Dstat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#nfs-traffic"&gt;NFS Traffic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#closing-remarks"&gt;Closing Remarks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id="environment"&gt;Environment&lt;a class="headerlink" href="#environment" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this small experiment we just need two Linux machines on a
local network, where one …&lt;/p&gt;</summary><content type="html">&lt;p&gt;This article illustrates how the &lt;a href="https://en.wikipedia.org/wiki/Virtual_memory"&gt;virtual memory (VM)&lt;/a&gt; subsystem of
the &lt;a href="https://en.wikipedia.org/wiki/Linux"&gt;Linux kernel&lt;/a&gt; is able to cache files that are located on
an &lt;a href="https://en.wikipedia.org/wiki/Network_File_System"&gt;NFS&lt;/a&gt; server.&lt;/p&gt;
&lt;div class="toc"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#environment"&gt;Environment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#high-level-view"&gt;High-Level View&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#dstat"&gt;Dstat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#nfs-traffic"&gt;NFS Traffic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#closing-remarks"&gt;Closing Remarks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id="environment"&gt;Environment&lt;a class="headerlink" href="#environment" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this small experiment we just need two Linux machines on a
local network, where one acts as &lt;a href="https://en.wikipedia.org/wiki/Network_File_System"&gt;NFS&lt;/a&gt; server and the other
one as NFS client. With a current Linux distribution like
&lt;a href="https://en.wikipedia.org/wiki/Fedora_(operating_system)"&gt;Fedora&lt;/a&gt; 26 you get &lt;a href="https://en.wikipedia.org/wiki/Network_File_System#NFSv4"&gt;NFSv4&lt;/a&gt; if you don't do
anything special.&lt;/p&gt;
&lt;p&gt;The following results are from a &lt;a href="https://en.wikipedia.org/wiki/Gigabit_Ethernet#1000BASE-T"&gt;1 GBit ethernet&lt;/a&gt; network where the
NFS client has 16 GB RAM and both machines run Fedora 26.&lt;/p&gt;
&lt;h2 id="high-level-view"&gt;High-Level View&lt;a class="headerlink" href="#high-level-view" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A simple way to read over the network from an NFS filesystem
without yielding disk IO on the client is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;empty the VM cache - e.g. rebooting the client and server
  or via executing &lt;code&gt;free &amp;amp;&amp;amp; sync &amp;amp;&amp;amp; echo 3 &amp;gt; /proc/sys/vm/drop_caches &amp;amp;&amp;amp;
  free&lt;/code&gt; on both machines&lt;/li&gt;
&lt;li&gt;on the client: &lt;code&gt;cat&lt;/code&gt; a relatively large file from a NFS
   filesystem to &lt;code&gt;/dev/null&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The file should be large enough such that we can easily measure
some metrics but small enough to fit into RAM.&lt;/p&gt;
&lt;p&gt;In our environment the 4.2 GB backup copy of the &lt;a href="https://en.wikipedia.org/wiki/John_Woo"&gt;John Woo&lt;/a&gt; movie
&lt;a href="https://en.wikipedia.org/wiki/The_Killer_(1989_film)"&gt;'The Killer'&lt;/a&gt; is well suited:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;The_Killer.iso&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/dev/null
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Z_shell"&gt;zsh&lt;/a&gt; time builtin reports:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mf"&gt;0.00&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.08&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;sys&lt;/span&gt;&lt;span class="n"&gt;tem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cpu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;38.373&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;to&lt;/span&gt;&lt;span class="n"&gt;tal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That means it took 38 seconds to transfer that 4.2 GiB file. This is
plausible because the resulting read rate of 113 MiB/s is close
to the wire speed (&lt;code&gt;10^9/8/1024/1024&lt;/code&gt;) minus the expected protocol overhead.&lt;/p&gt;
&lt;p&gt;Executing the read command&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;The_Killer.iso&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/dev/null
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;a second and third time is way faster:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mf"&gt;0.00&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.57&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;sys&lt;/span&gt;&lt;span class="n"&gt;tem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;99&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cpu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.578&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;to&lt;/span&gt;&lt;span class="n"&gt;tal&lt;/span&gt;
&lt;span class="mf"&gt;0.00&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.44&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;sys&lt;/span&gt;&lt;span class="n"&gt;tem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;98&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cpu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.447&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;to&lt;/span&gt;&lt;span class="n"&gt;tal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Just half a second.&lt;/p&gt;
&lt;p&gt;After clearing the VM cache with&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gh"&gt;#&lt;/span&gt; free &amp;amp;&amp;amp; sync &amp;amp;&amp;amp; echo 3 &amp;gt; /proc/sys/vm/drop_caches &amp;amp;&amp;amp; free
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;where the final free reports&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;buff/cache
1871568
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and reading the file just another time we are back at the initial
timing:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mf"&gt;0.02&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.26&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;sys&lt;/span&gt;&lt;span class="n"&gt;tem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cpu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;38.551&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;to&lt;/span&gt;&lt;span class="n"&gt;tal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A &lt;code&gt;free&lt;/code&gt; then reports&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;buff/cache
6267676
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is plausible as well, i.e. &lt;code&gt;(6267676-1871568)/1024/1024&lt;/code&gt;
is close to the 4.2 GB file size.&lt;/p&gt;
&lt;p&gt;If we have a rough idea how the VM subsystem works with a local
filsystem in a common OS kernel (like Linux) all this isn't
surprising. One just might wonder how the kernel decides that it
is safe to reuse the VM cache since the file could have changed
on the server (e.g. locally or by another NFS client).&lt;/p&gt;
&lt;p&gt;We can verify that the kernel is able to detect file changes by
other parties via touching the file on the server, e.g.:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;touch&lt;span class="w"&gt; &lt;/span&gt;The_Killer.iso
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After that, reading the file again on the client takes the initial
amount of time (39 seconds).&lt;/p&gt;
&lt;h2 id="dstat"&gt;Dstat&lt;a class="headerlink" href="#dstat" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When running the &lt;a href="http://dag.wiee.rs/home-made/dstat/"&gt;&lt;code&gt;dstat&lt;/code&gt; command&lt;/a&gt; on the client we can obtain a
more detailed picture. For example:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;dstat&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;-D&lt;span class="w"&gt; &lt;/span&gt;total&lt;span class="w"&gt; &lt;/span&gt;-g&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;-N&lt;span class="w"&gt; &lt;/span&gt;enp0s31f6&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;--vm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By default, &lt;code&gt;dstat&lt;/code&gt; repeatedly averages over 1 second, i.e. it prints every
second a new line.&lt;/p&gt;
&lt;p&gt;The dstat output during the first file read:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Dstat output during first read" src="https://gms.tf/image/dstat-first.png"&gt;&lt;/p&gt;
&lt;p&gt;We can observe a few things in the listing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the network receive rate matches the computed read rate (modulo
  protocol overhead) and since reads need to be acknowledged
  the outgoing network traffic increases as well&lt;/li&gt;
&lt;li&gt;directly after starting the read the VM heavily allocates and
  frees caches pages (in the order of &lt;code&gt;60 * 10^3&lt;/code&gt; pages or so)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The work the VM subsystem is doing is plausible. The system has a
page size of 4 KiB and thus the amount of cache pages is
sufficient to deal with the read rate.&lt;/p&gt;
&lt;p&gt;The listing for the second read is much shorter:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Dstat output during second read" src="https://gms.tf/image/dstat-cached.png"&gt;&lt;/p&gt;
&lt;p&gt;Here we don't see much network traffic, but we see a clear
increase in traffic that could be explained by some NFS
communication where the client inquires the server whether the
file is outdated or not.&lt;/p&gt;
&lt;p&gt;Also, as expected, the VM subsystem isn't busy with allocations
and frees as before.&lt;/p&gt;
&lt;h2 id="nfs-traffic"&gt;NFS Traffic&lt;a class="headerlink" href="#nfs-traffic" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To get an idea how the &lt;a href="https://en.wikipedia.org/wiki/Network_File_System"&gt;NFS&lt;/a&gt; client detects file changes we can
capture the network traffic and inspect with an analyzer like
&lt;a href="https://en.wikipedia.org/wiki/Wireshark"&gt;Wireshark&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In case directly capturing with Wireshark isn't an option, a
simple alternative is to capture with &lt;a href="https://en.wikipedia.org/wiki/Tcpdump"&gt;tcpdump&lt;/a&gt; to a file and open
that file later with wireshark, e.g.:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;# &lt;/span&gt;tcpdump&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;enp0s31f6&lt;span class="w"&gt; &lt;/span&gt;-s0&lt;span class="w"&gt; &lt;/span&gt;-w&lt;span class="w"&gt; &lt;/span&gt;/var/tmp/nfs.dump
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The NFS flow for the second file read is quite compact in the
wireshark overview:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Wireshark NFS overview" src="https://gms.tf/image/wireshark-nfs-overview.png"&gt;&lt;/p&gt;
&lt;p&gt;As expected, it is &lt;a href="https://en.wikipedia.org/wiki/Network_File_System#NFSv4"&gt;NFS version 4&lt;/a&gt; and there are just a few query
operations.&lt;/p&gt;
&lt;p&gt;In detail the second &lt;code&gt;GETATTR&lt;/code&gt; reply:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Wireshark NFS details" src="https://gms.tf/image/wireshark-nfs-detail.png"&gt;&lt;/p&gt;
&lt;p&gt;We observe that the server replies that the file is a regular
file (&lt;code&gt;NF4REG&lt;/code&gt;) and reports its change-ID and file-ID.&lt;/p&gt;
&lt;p&gt;The file-ID is conceptually similar to an &lt;a href="https://en.wikipedia.org/wiki/Inode"&gt;inode&lt;/a&gt; and thus the NFS
client can compare the change-ID with the one obtained from last
time to decide if it can reuse the pages from the &lt;a href="https://en.wikipedia.org/wiki/Virtual_memory"&gt;VM cache&lt;/a&gt; or if
it has to retrieve the change file from the server.&lt;/p&gt;
&lt;p&gt;Sure enough, after touching the file the server sends a new
change-ID, i.e. 17002 after the first touch and then 17003 after
the second touch. As expected, the file-ID doesn't change.&lt;/p&gt;
&lt;p&gt;Why does the client issues two &lt;code&gt;GETTATTR&lt;/code&gt; requests? The first is for
the directory the file is located in (&lt;code&gt;NF4DIR&lt;/code&gt;).&lt;/p&gt;
&lt;h2 id="closing-remarks"&gt;Closing Remarks&lt;a class="headerlink" href="#closing-remarks" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So when does the VM caching matter? Or, how can accidentally work
against this mechanism when using NFS?&lt;/p&gt;
&lt;p&gt;Say, entirely hypothetical, you have a &lt;a href="https://en.wikipedia.org/wiki/Computer_cluster"&gt;compute cluster&lt;/a&gt; where
typical compute jobs are actually program chains where the output
of one program is the input of the next one.  Also assume that
the working directories are shared via NFS for flexibility and
redundancy. For example, when one cluster node crashes in the
middle of a chain then the chain can be completed on another node
without having to recompute everything.&lt;/p&gt;
&lt;p&gt;In that scenario, the best case would be: the complete chain is
executed on one cluster node. A &lt;a href="https://en.wikipedia.org/wiki/Job_scheduler"&gt;job-scheduler&lt;/a&gt; only schedules the
complete chain to a cluster node. It doesn't re-schedule
single programs of a chain between cluster nodes. Then the
input for the program next in chain comes from VM subsystem and
doesn't need to be transmitted over the network.&lt;/p&gt;
&lt;p&gt;In contrast to that, since the work directories are shared, it is
also possible to have finer job scheduling granularity, i.e. for
each program of a chain. But this would increase the load on the
NFS server.  In the worst-case the NFS server's outgoing network
traffic would multiply because the result of one chain program
executed on cluster node A would have to be retrieved from the
NFS server by the next chain program executed on cluster node B.&lt;/p&gt;
&lt;p&gt;Similar reasoning applies to other network filesystems (and other
operating systems with a VM subsystem) and thus
it makes sense to build a chain-to-node-affinity mechanism into the job
scheduler such that the VM cache re-use is maximized in such a
chain-job environment.&lt;/p&gt;</content><category term="linux"></category><category term="nfs"></category></entry><entry><title>Check CPU Microcode Version on Linux</title><link href="https://gms.tf/check-cpu-microcode-version-on-linux.html" rel="alternate"></link><published>2017-07-01T10:10:00+02:00</published><updated>2017-07-01T10:10:00+02:00</updated><author><name>Georg Sauthoff</name></author><id>tag:gms.tf,2017-07-01:/check-cpu-microcode-version-on-linux.html</id><summary type="html">&lt;p&gt;Debian recently released a &lt;a href="https://lists.debian.org/debian-devel/2017/06/msg00308.html"&gt;warning advisory regarding a hardware
bug in the hyperthreading implementation on certain Skylake/Kaby
Lake Intel CPUs&lt;/a&gt;. It can be mitigated by a &lt;a href="https://en.wikipedia.org/wiki/Microcode"&gt;microcode&lt;/a&gt; firmware
update - at least on some models. This article is about checking
a non-Debian system for this issue and verifying if the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Debian recently released a &lt;a href="https://lists.debian.org/debian-devel/2017/06/msg00308.html"&gt;warning advisory regarding a hardware
bug in the hyperthreading implementation on certain Skylake/Kaby
Lake Intel CPUs&lt;/a&gt;. It can be mitigated by a &lt;a href="https://en.wikipedia.org/wiki/Microcode"&gt;microcode&lt;/a&gt; firmware
update - at least on some models. This article is about checking
a non-Debian system for this issue and verifying if the right
microcode is in place.&lt;/p&gt;
&lt;p&gt;The below console snippets are from a Dell notebook with Skylake
CPU that runs Fedora 25. It turns out that Fedora, in contrast to
Debian, installs some firmware packages, by default, including
Intel microcode images (cf. &lt;code&gt;microcode_ctl&lt;/code&gt;). Thus, a Fedora
system on Skylake should already run with the microcode version
that includes the fix.&lt;/p&gt;
&lt;p&gt;Check for certain CPU features - e.g. if hypterthreading is
enabled:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;\&amp;lt;ht\&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/proc/cpuinfo&lt;span class="w"&gt; &lt;/span&gt;-q&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="go"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Display CPU model, stepping and active microcode version:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;stepping\|model\|microcode&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/proc/cpuinfo
&lt;span class="go"&gt;model       : 78&lt;/span&gt;
&lt;span class="go"&gt;model name  : Intel(R) Core(TM) i7-6600U CPU @ 2.60GHz&lt;/span&gt;
&lt;span class="go"&gt;stepping    : 3&lt;/span&gt;
&lt;span class="go"&gt;microcode   : 0xba&lt;/span&gt;
&lt;span class="go"&gt;[..]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The advisory states that Skylake model 78, stepping 3 is affected
and that microcode version &lt;code&gt;0xba&lt;/code&gt; includes the fix.&lt;/p&gt;
&lt;p&gt;Investigate whether the microcode was loaded by the BIOS or by the kernel:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;# &lt;/span&gt;journalctl&lt;span class="w"&gt; &lt;/span&gt;--no-hostname&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;short-monotonic&lt;span class="w"&gt; &lt;/span&gt;--boot&lt;span class="w"&gt; &lt;/span&gt;-0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;1,/PM: Preparing system for sleep/p&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;microcode\|smp&amp;#39;&lt;/span&gt;
&lt;span class="go"&gt;[    0.000000] microcode: microcode updated early to revision 0xba, \&lt;/span&gt;
&lt;span class="go"&gt;                   date = 2017-04-09&lt;/span&gt;
&lt;span class="go"&gt;[    0.000000] smpboot: Allowing 4 CPUs, 0 hotplug CPUs&lt;/span&gt;
&lt;span class="go"&gt;[    0.040087] smpboot: Max logical packages: 2&lt;/span&gt;
&lt;span class="go"&gt;[    0.056402] smpboot: CPU0: Intel(R) Core(TM) i7-6600U CPU @ 2.60GHz \&lt;/span&gt;
&lt;span class="go"&gt;                   (family: 0x6, model: 0x4e, stepping: 0x3)&lt;/span&gt;
&lt;span class="go"&gt;[    0.056975] smp: Bringing up secondary CPUs ...&lt;/span&gt;
&lt;span class="go"&gt;[    0.239023] smp: Brought up 1 node, 4 CPUs&lt;/span&gt;
&lt;span class="go"&gt;[    0.239023] smpboot: Total of 4 processors activated (22476.05 BogoMIPS)&lt;/span&gt;
&lt;span class="go"&gt;[    0.693589] microcode: sig=0x406e3, pf=0x80, revision=0xba&lt;/span&gt;
&lt;span class="go"&gt;[    0.693671] microcode: Microcode Update Driver: v2.2.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That means the microcode image in the BIOS is older, thus, the
Kernel loaded a newer version (the microcode date also matches
the one mentioned in the advisory).&lt;/p&gt;
&lt;p&gt;After a BIOS update, check that the BIOS loads the microcode
before kernel start:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;# &lt;/span&gt;journalctl&lt;span class="w"&gt; &lt;/span&gt;--no-hostname&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;short-monotonic&lt;span class="w"&gt; &lt;/span&gt;--boot&lt;span class="w"&gt; &lt;/span&gt;-0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;1,/PM: Preparing system for sleep/p&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;microcode\|smp&amp;#39;&lt;/span&gt;
&lt;span class="go"&gt;[    0.000000] smpboot: Allowing 4 CPUs, 0 hotplug CPUs&lt;/span&gt;
&lt;span class="go"&gt;[    0.039057] smpboot: Max logical packages: 2&lt;/span&gt;
&lt;span class="go"&gt;[    0.054709] smpboot: CPU0: Intel(R) Core(TM) i7-6600U CPU @ 2.60GHz \&lt;/span&gt;
&lt;span class="go"&gt;                   (family: 0x6, model: 0x4e, stepping: 0x3)&lt;/span&gt;
&lt;span class="go"&gt;[    0.055000] smp: Bringing up secondary CPUs ...&lt;/span&gt;
&lt;span class="go"&gt;[    0.235034] smp: Brought up 1 node, 4 CPUs&lt;/span&gt;
&lt;span class="go"&gt;[    0.235034] smpboot: Total of 4 processors activated (22560.93 BogoMIPS)&lt;/span&gt;
&lt;span class="go"&gt;[    0.711458] microcode: sig=0x406e3, pf=0x80, revision=0xba&lt;/span&gt;
&lt;span class="go"&gt;[    0.711662] microcode: Microcode Update Driver: v2.2.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;(there is no &lt;code&gt;microcode udpated early&lt;/code&gt; message, anymore)&lt;/p&gt;
&lt;p&gt;Modern CPU &lt;a href="https://en.wikipedia.org/wiki/Microcode"&gt;microcode&lt;/a&gt;, like used by Intel CPUs, isn't persistent,
i.e. it must be loaded at each boot, either by the BIOS or by the
kernel. Apparently, it even has to be reloaded during resume
after a suspend-to-RAM (cf. the kernel messages).&lt;/p&gt;</content><category term="linux"></category><category term="firmware"></category><category term="dell"></category></entry><entry><title>Fedora as Grml replacement</title><link href="https://gms.tf/fedora-as-grml-replacement.html" rel="alternate"></link><published>2017-03-12T21:00:00+01:00</published><updated>2017-03-12T21:00:00+01:00</updated><author><name>Georg Sauthoff</name></author><id>tag:gms.tf,2017-03-12:/fedora-as-grml-replacement.html</id><summary type="html">&lt;p&gt;&lt;a href="https://grml.org/"&gt;Grml&lt;/a&gt; is a Linux Live CD distribution geared towards system
administration tasks and other console work. Unfortunately, its
development has slowed down in the past years, i.e. the latest
stable release is from 2014. In 2017, when dealing with modern
hardware, modern features like Btrfs, SELinux etc. this is …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://grml.org/"&gt;Grml&lt;/a&gt; is a Linux Live CD distribution geared towards system
administration tasks and other console work. Unfortunately, its
development has slowed down in the past years, i.e. the latest
stable release is from 2014. In 2017, when dealing with modern
hardware, modern features like Btrfs, SELinux etc. this is a deal
breaker. It turns out that &lt;a href="https://en.wikipedia.org/wiki/Fedora_(operating_system)"&gt;Fedora&lt;/a&gt;, when installed on a USB mass
storage device, is a good substitute for traditional Linux Live
CDs like Grml.&lt;/p&gt;
&lt;h2 id="how-it-works"&gt;How it works&lt;a class="headerlink" href="#how-it-works" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A very fast and convenient method to install Fedora on a USB
stick is to use &lt;a href="http://libguestfs.org/virt-builder.1.html"&gt;&lt;code&gt;virt-builder&lt;/code&gt;&lt;/a&gt;, e.g.:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;virt-builder&lt;span class="w"&gt; &lt;/span&gt;fedora-25&lt;span class="w"&gt; &lt;/span&gt;--hostname&lt;span class="w"&gt; &lt;/span&gt;rescue.example.org&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
--ssh-inject&lt;span class="w"&gt; &lt;/span&gt;root:file:&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$pubkey&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--root-password&lt;span class="w"&gt; &lt;/span&gt;file:&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$pwfile&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
--update&lt;span class="w"&gt; &lt;/span&gt;--install&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;paste&lt;span class="w"&gt; &lt;/span&gt;-d,&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;package.list&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
--run&lt;span class="w"&gt; &lt;/span&gt;guest-setup.sh&lt;span class="w"&gt; &lt;/span&gt;--selinux-relabel&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
-o&lt;span class="w"&gt; &lt;/span&gt;/dev/sdz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href="http://libguestfs.org/virt-builder.1.html"&gt;&lt;code&gt;virt-builder&lt;/code&gt; command&lt;/a&gt; is probably mostly used for fast
generation of virtual machine images but it works as well for
bare-metal installations. It is so fast because it starts from
filesystem-templates.&lt;/p&gt;
&lt;p&gt;In the above example, the shell script &lt;code&gt;guest-setup.sh&lt;/code&gt; applies
some defaults and other post-installation customizations in the
target system.&lt;/p&gt;
&lt;p&gt;The result can be easily tested with &lt;a href="http://wiki.qemu-project.org/Features/KVM"&gt;QEMU/KVM&lt;/a&gt;, e.g.:&lt;/p&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;qemu-system-x86_64&lt;span class="w"&gt; &lt;/span&gt;-enable-kvm&lt;span class="w"&gt; &lt;/span&gt;-drive&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/sdz,if&lt;span class="o"&gt;=&lt;/span&gt;virtio,format&lt;span class="o"&gt;=&lt;/span&gt;raw&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2048&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-netdev&lt;span class="w"&gt; &lt;/span&gt;bridge,id&lt;span class="o"&gt;=&lt;/span&gt;nd0,name&lt;span class="o"&gt;=&lt;/span&gt;tap0,br&lt;span class="o"&gt;=&lt;/span&gt;virbr0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-device&lt;span class="w"&gt; &lt;/span&gt;e1000,netdev&lt;span class="o"&gt;=&lt;/span&gt;nd0,id&lt;span class="o"&gt;=&lt;/span&gt;d0&lt;span class="w"&gt;  &lt;/span&gt;-display&lt;span class="w"&gt; &lt;/span&gt;curses
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="the-code"&gt;The Code&lt;a class="headerlink" href="#the-code" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I've &lt;a href="https://github.com/gsauthof/playbook/tree/master/fedora/rescue-stick"&gt;published some scripts to generate such a Fedora based USB
stick in a Git repository&lt;/a&gt;. The repository also contains some
more details in a README including a detailed comparison with
Grml.&lt;/p&gt;
&lt;h2 id="addendum"&gt;Addendum&lt;a class="headerlink" href="#addendum" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Also, nowadays, the traditional Linux Live CD approach is a
little bit outdated. Many systems don't even have a CDROM drive
anymore for good reason. Sophisticated distributions like Grml
are hybrid, i.e. they can also be booted from a USB stick, but
they don't make use of the extra space or the fact that the stick
is writable, by default. Grml even supports customizations like
adding a writable filesystem but such changes are kind of
tedious.&lt;/p&gt;
&lt;p&gt;Grml doesn't just come with good defaults (e.g. zsh login shell),
the team also has a talent choosing great release names (e.g.
&lt;a href="https://grml.org/changelogs/README-grml-2011.12/"&gt;Knecht Rootrecht&lt;/a&gt;).&lt;/p&gt;</content><category term="linux"></category><category term="rescue"></category><category term="playbook"></category><category term="virt-builder"></category></entry><entry><title>Btrfs requires noatime</title><link href="https://gms.tf/btrfs-requires-noatime.html" rel="alternate"></link><published>2017-02-08T21:10:00+01:00</published><updated>2017-02-08T21:10:00+01:00</updated><author><name>Georg Sauthoff</name></author><id>tag:gms.tf,2017-02-08:/btrfs-requires-noatime.html</id><summary type="html">&lt;p&gt;Traditionally, UNIX filesystems also maintain the &lt;a href="https://en.wikipedia.org/wiki/Stat_(system_call)"&gt;access time
(atime)&lt;/a&gt; of a file. This is very much an anti-feature because it
yields a write operation for each read operation. Which is
obviously bad for performance. Since &lt;a href="https://en.wikipedia.org/wiki/Btrfs"&gt;Btrfs&lt;/a&gt; is a &lt;a href="https://en.wikipedia.org/wiki/Copy-on-write"&gt;copy-on-write
(COW)&lt;/a&gt; filesystem maintaining atimes is even more painful. Thus, a
sensible …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Traditionally, UNIX filesystems also maintain the &lt;a href="https://en.wikipedia.org/wiki/Stat_(system_call)"&gt;access time
(atime)&lt;/a&gt; of a file. This is very much an anti-feature because it
yields a write operation for each read operation. Which is
obviously bad for performance. Since &lt;a href="https://en.wikipedia.org/wiki/Btrfs"&gt;Btrfs&lt;/a&gt; is a &lt;a href="https://en.wikipedia.org/wiki/Copy-on-write"&gt;copy-on-write
(COW)&lt;/a&gt; filesystem maintaining atimes is even more painful. Thus, a
sensible recommendation is to make sure that every filesystem is
mounted with the &lt;code&gt;noatime&lt;/code&gt; option.  Especially, if it is a Btrfs
filesystem.&lt;/p&gt;
&lt;h2 id="btrfs-case-study"&gt;Btrfs Case Study&lt;a class="headerlink" href="#btrfs-case-study" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A typical example of how writing the atime can significantly
affect performance.&lt;/p&gt;
&lt;p&gt;The symptoms: an &lt;a href="https://en.wikipedia.org/wiki/Rsync"&gt;rsync&lt;/a&gt; job from a Btrfs filesystem
(located on an SSD) to an external USB 3 disk drive with XFS runs
with ~ 17 MiB/s while &lt;code&gt;iotop&lt;/code&gt; and &lt;code&gt;dstat&lt;/code&gt; show significantly
higher IO values for the source device, e.g. ~ 60 MiB/s.&lt;/p&gt;
&lt;p&gt;Reasons: This Btrfs filesystem is mounted with default options,
that means that instead of &lt;code&gt;noatime&lt;/code&gt; the &lt;code&gt;relatime&lt;/code&gt; is active,
resulting in atime updates for effectively each file.&lt;/p&gt;
&lt;p&gt;In addition to that, the filesystem contains some snapshots, i.e.
for all subvolumes there is also one or more snapshots. Creating
a filesystem snapshot is very cheap on &lt;a href="https://en.wikipedia.org/wiki/Btrfs"&gt;Btrfs&lt;/a&gt; because of
its &lt;a href="https://en.wikipedia.org/wiki/Copy-on-write"&gt;COW&lt;/a&gt; design. An atime update of a snapshotted file only
updates the atime of one copy. Thus, in the likely case that the
filesystem sector with the atime is still shared it has to be
copied on that atime write. Meaning 2 or more write operations as
a result of one read.&lt;/p&gt;
&lt;p&gt;Resolution: After canceling the rsync command,
remounting the Btrfs filesystem with &lt;code&gt;noatime&lt;/code&gt; and restarting
the rsync job it sure enough performs much better, i.e.
the numbers reported by rsync match the dstat ones, as expected.&lt;/p&gt;
&lt;p&gt;Note that the number of files included in a snapshot is
most relevant for this issue, not necessarily the number of
snapshots.&lt;/p&gt;
&lt;p&gt;If you are really unlucky, running a backup job (or even just a
grep) on a Btrfs filesystem mounted without noatime might even
yield out-of-space errors in case all the copy-on-write atime
updates exceed the available free space.&lt;/p&gt;
&lt;h2 id="relatime"&gt;Relatime&lt;a class="headerlink" href="#relatime" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since 2009 or so Linux kernels by default mount filesystems with
the &lt;code&gt;relatime&lt;/code&gt; option. With this options, the atime is updated
somewhat less frequently. That means under the presence of reads,
it is updated at least once a day:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div class="m-code"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;relatime
   Update  inode access times relative to modify or change
   time.  Access time is only updated if the previous
   access time was earlier than the current modify or
   change time.  (Similar to noatime, but it doesn&amp;#39;t break
   mutt or other applications that need to know  if  a
   file has been read since the last time it was modified.)

   Since  Linux  2.6.30,  the  kernel defaults to the
   behavior provided by this option (unless noatime was
   specified), and the strictatime option is required to
   obtain traditional semantics.  In addition, since Linux
   2.6.30, the file&amp;#39;s last access time is always updated
   if it is more than 1 day old.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/blockquote&gt;
&lt;p&gt;(&lt;a href="https://www.freebsd.org/cgi/man.cgi?query=mount&amp;amp;apropos=0&amp;amp;sektion=8&amp;amp;manpath=CentOS+7.1&amp;amp;arch=default&amp;amp;format=html"&gt;mount(8)&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Thus, &lt;code&gt;relatime&lt;/code&gt; doesn't help much with the principal cause for
the described performance issue. You still likely get massive
atime update induced writes during bulk read-only activity like
backup or search jobs. You only have to experience a timespan
greater than 24h were most files aren't read. A pretty standard
scenario.&lt;/p&gt;
&lt;p&gt;Unfortunately, switching the system default from &lt;code&gt;relatime&lt;/code&gt; to &lt;code&gt;noatime&lt;/code&gt; isn't
possible (as of 2017-02). Thus, one has to remember to always specify
&lt;code&gt;noatime&lt;/code&gt;. Think &lt;code&gt;mount -o noatime ...&lt;/code&gt; and add it to each &lt;code&gt;/etc/fstab&lt;/code&gt;
entry.&lt;/p&gt;
&lt;h2 id="testing"&gt;Testing&lt;a class="headerlink" href="#testing" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Testing the effect of atime uptime in the presence of snapshots
is easier when the Btrfs filesystem is mounted with
&lt;code&gt;strictatime&lt;/code&gt;. This overrides the &lt;code&gt;relatime&lt;/code&gt; default option.
The time attributes of a file or directory can be displayed with
&lt;code&gt;ls&lt;/code&gt; but the GNU utility &lt;code&gt;stat&lt;/code&gt; is more convenient for printing
all timestamps.&lt;/p&gt;
&lt;h2 id="ps"&gt;P.S.&lt;a class="headerlink" href="#ps" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are use-cases for an actively maintained file atime.
Examples are measuring the usage of installed binaries (cf.
Debian's popcontest) or detecting unread mails. But there are
better alternatives to implement such tasks and thus those aren't
very convincing arguments for enabling atime writing, by default
(be it relative or even strict). In conclusion, writing the
access time means much pain with little gain.&lt;/p&gt;
&lt;h2 id="see-also"&gt;See also&lt;a class="headerlink" href="#see-also" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lwn.net/Articles/499293/"&gt;Atime and btrfs: a bad combination?&lt;/a&gt; - this is also an
  counter-example to &lt;a href="https://en.wikipedia.org/wiki/Betteridge's_law_of_headlines"&gt;Betteridge's law of headlines&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="linux"></category><category term="btrfs"></category></entry></feed>