<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://andi-zimmerer.com//feed.xml" rel="self" type="application/atom+xml"/><link href="https://andi-zimmerer.com//" rel="alternate" type="text/html" hreflang="en"/><updated>2026-02-20T08:39:05+00:00</updated><id>https://andi-zimmerer.com//feed.xml</id><title type="html">blank</title><subtitle>Technical explorations of database systems research, focusing on architecture, optimization, and system design through the lens of doctoral research. </subtitle><entry><title type="html">Benchmarking Semantic Query Processing Systems</title><link href="https://andi-zimmerer.com//posts/sembench.html" rel="alternate" type="text/html" title="Benchmarking Semantic Query Processing Systems"/><published>2026-02-16T00:00:00+00:00</published><updated>2026-02-16T00:00:00+00:00</updated><id>https://andi-zimmerer.com//posts/sembench</id><content type="html" xml:base="https://andi-zimmerer.com//posts/sembench.html"><![CDATA[]]></content><author><name></name></author><category term="Semantic Query Engines"/><category term="Benchmarking"/><summary type="html"><![CDATA[Semantic query processing is emerging as a new layer atop relational engines, elevating LLM-backed semantic operators to first-class SQL primitives for multimodal data. We present SemBench, the first benchmark to rigorously evaluate these systems end-to-end, and outline our roadmap towards our own system, Spectra, to make semantic operators affordable at scale.]]></summary></entry><entry><title type="html">Continued Investments in Price Performance and Faster Top-K Queries</title><link href="https://andi-zimmerer.com//posts/snowflake-topk-2.html" rel="alternate" type="text/html" title="Continued Investments in Price Performance and Faster Top-K Queries"/><published>2024-08-07T00:00:00+00:00</published><updated>2024-08-07T00:00:00+00:00</updated><id>https://andi-zimmerer.com//posts/snowflake-topk-2</id><content type="html" xml:base="https://andi-zimmerer.com//posts/snowflake-topk-2.html"><![CDATA[]]></content><author><name></name></author><category term="Snowflake"/><category term="top-k"/><summary type="html"><![CDATA[Performance optimizations of `ORDER BY ... LIMIT k`, also known as Top-K queries in SQL, in the Snowflake Data Warehouse. Joint work with Juliane Waack. Part 2.]]></summary></entry><entry><title type="html">Speeding up Top-K Queries in Snowflake</title><link href="https://andi-zimmerer.com//posts/snowflake-topk.html" rel="alternate" type="text/html" title="Speeding up Top-K Queries in Snowflake"/><published>2023-06-23T00:00:00+00:00</published><updated>2023-06-23T00:00:00+00:00</updated><id>https://andi-zimmerer.com//posts/snowflake-topk</id><content type="html" xml:base="https://andi-zimmerer.com//posts/snowflake-topk.html"><![CDATA[]]></content><author><name></name></author><category term="Snowflake"/><category term="top-k"/><summary type="html"><![CDATA[Performance optimizations of `ORDER BY ... LIMIT k`, also known as Top-K queries in SQL, in the Snowflake Data Warehouse. Joint work with Juliane Waack.]]></summary></entry><entry><title type="html">My Journey to Becoming a TiKV Contributor</title><link href="https://andi-zimmerer.com//posts/lfx-tikv.html" rel="alternate" type="text/html" title="My Journey to Becoming a TiKV Contributor"/><published>2021-05-31T00:00:00+00:00</published><updated>2021-05-31T00:00:00+00:00</updated><id>https://andi-zimmerer.com//posts/lfx-tikv</id><content type="html" xml:base="https://andi-zimmerer.com//posts/lfx-tikv.html"><![CDATA[<blockquote class="block-tip"> <h5 id="tip">TIP</h5> <p>This blog post is also available on the <a href="https://tikv.org/blog/lfx-2021-copr-v2/">TiKV blog</a> and the <a href="https://www.cncf.io/blog/2021/07/26/mentorship-spotlight-looking-back-at-the-lfx-mentorship-program-spring-21-my-journey-to-becoming-a-tikv-contributor/?hss_channel=tw-3286770860">CNCF blog</a>.</p> </blockquote>]]></content><author><name></name></author><category term="TiKV"/><category term="Community"/><category term="Open-Source"/><summary type="html"><![CDATA[I had the pleasure the work on TiKV, a distributed key-value store in Rust that serves as a storage engine for TiDB, as an LFX Program Mentee in 2021. The goal was to implement a "pluggable" coprocessor, similar to HBase's coprocessor, where users can leverage the computational power of storage nodes and directory execute arbitrary computation on them.]]></summary></entry><entry><title type="html">Automatic Flamegraphs for Benchmarks in Rust</title><link href="https://andi-zimmerer.com//posts/criterion-flamegraphs.html" rel="alternate" type="text/html" title="Automatic Flamegraphs for Benchmarks in Rust"/><published>2021-01-22T00:00:00+00:00</published><updated>2021-01-22T00:00:00+00:00</updated><id>https://andi-zimmerer.com//posts/criterion-flamegraphs</id><content type="html" xml:base="https://andi-zimmerer.com//posts/criterion-flamegraphs.html"><![CDATA[<p>This is just a short post about something I recently discovered in the Rust ecosystem: How to automatically create flamegraphs for benchmarks written with <code class="language-plaintext highlighter-rouge">criterion</code> using the <code class="language-plaintext highlighter-rouge">pprof</code> crate.</p> <hr/> <blockquote class="block-tip"> <h5 id="update">Update</h5> <p>Based on this blog post, <code class="language-plaintext highlighter-rouge">pprof</code> now ships with a <a href="https://docs.rs/pprof/0.4.2/pprof/criterion/struct.PProfProfiler.html">custom profiler for Criterion</a> since version 0.4.2! Make sure to check out <a href="https://github.com/tikv/pprof-rs/blob/v0.4.2/examples/criterion.rs">this example</a> and enable <code class="language-plaintext highlighter-rouge">"criterion"</code> and <code class="language-plaintext highlighter-rouge">"flamegraph"</code> crate features.</p> </blockquote> <h2 id="introduction">Introduction</h2> <p><a href="https://github.com/bheisler/criterion.rs">Criterion</a> is a well-known and often-used benchmarking framework in the Rust ecosystem. If you’ve not yet heard of it, definitely check it out!</p> <p>Since <code class="language-plaintext highlighter-rouge">v0.3</code>, Criterion supports <a href="https://bheisler.github.io/criterion.rs/book/user_guide/profiling.html#implementing-in-process-profiling-hooks">in-process profiling hooks</a>. They allow us to use a custom profiler while running benchmarks. After registering a custom profiler, we can enable them by running the benchmark suite with the <code class="language-plaintext highlighter-rouge">--profile-time</code> flag.</p> <p>Having hooks for a custom profiler for your benchmarks allows you to do <em>awesome</em> stuff, for example generating flamegraphs for every benchmark with <a href="https://crates.io/crates/pprof"><code class="language-plaintext highlighter-rouge">pprof</code></a>.</p> <h2 id="background">Background</h2> <p>One question I often ask myself when looking at benchmarks is:</p> <blockquote> <p>“These numbers are great. But how can we do this faster? Where do we spend the most time?”</p> </blockquote> <p>This question can often be answered by looking at flamegraphs.</p> <p>Previously, I got my hands dirty using <a href="https://github.com/flamegraph-rs/flamegraph"><code class="language-plaintext highlighter-rouge">cargo-flamegraph</code></a>, which is a really good tool on its own. But the problem is that when using <a href="https://github.com/flamegraph-rs/flamegraph"><code class="language-plaintext highlighter-rouge">cargo-flamegraph</code></a> with benchmarks, you will usually get some unnecessary clutter, e.g. the setup routine for your benchmark and the enclosing framework code from Criterion.</p> <p>And here comes another cool Rust library into play: <a href="https://crates.io/crates/pprof"><code class="language-plaintext highlighter-rouge">pprof</code></a> with the <code class="language-plaintext highlighter-rouge">flamegraph</code> feature!</p> <p><a href="https://crates.io/crates/pprof"><code class="language-plaintext highlighter-rouge">pprof</code></a> is a CPU profiler that can be used to profile specific parts of your program on Linux. The best of all: It even supports generating flamegraphs with the feature flag <code class="language-plaintext highlighter-rouge">flamegraph</code>.</p> <p>Let’s directly dive in and create a <code class="language-plaintext highlighter-rouge">pprof</code> integration for Criterion!</p> <h2 id="setup">Setup</h2> <p>We will now create a custom profiler for <code class="language-plaintext highlighter-rouge">criterion</code> with <code class="language-plaintext highlighter-rouge">pprof</code> that will print flamegraphs for each benchmark.</p> <p>First, add the following dependencies to your <code class="language-plaintext highlighter-rouge">Cargo.toml</code>:</p> <div class="language-toml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">[dev-dependencies]</span>
<span class="py">pprof</span> <span class="o">=</span> <span class="p">{</span> <span class="py">version</span> <span class="p">=</span> <span class="s">"0.3"</span><span class="p">,</span> <span class="py">features</span> <span class="p">=</span> <span class="p">[</span><span class="s">"flamegraph"</span><span class="p">]</span> <span class="p">}</span>
<span class="py">criterion</span> <span class="p">=</span> <span class="s">"0.3"</span>
<span class="c"># criterion-macro = "0.3"  # optional, if you use custom test frameworks</span>
</code></pre></div></div> <p>Now create a new file in your <code class="language-plaintext highlighter-rouge">benches/</code> folder. Let’s call it <code class="language-plaintext highlighter-rouge">perf.rs</code>. Here we will implement our new <code class="language-plaintext highlighter-rouge">FlamegraphProfiler</code>.</p> <p>The interface for implementing a custom profiler is actually quite straight-forward. We only need to implement the <a href="https://docs.rs/criterion/*/criterion/profiler/trait.Profiler.html"><code class="language-plaintext highlighter-rouge">criterion::profiler::Profiler</code></a> trait from Criterion and we are good to go.</p> <div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">std</span><span class="p">::{</span><span class="nn">fs</span><span class="p">::</span><span class="n">File</span><span class="p">,</span> <span class="nn">os</span><span class="p">::</span><span class="nn">raw</span><span class="p">::</span><span class="nb">c_int</span><span class="p">,</span> <span class="nn">path</span><span class="p">::</span><span class="n">Path</span><span class="p">};</span>

<span class="k">use</span> <span class="nn">criterion</span><span class="p">::</span><span class="nn">profiler</span><span class="p">::</span><span class="n">Profiler</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">pprof</span><span class="p">::</span><span class="n">ProfilerGuard</span><span class="p">;</span>


<span class="cd">/// Small custom profiler that can be used with Criterion to create a flamegraph for benchmarks.</span>
<span class="cd">/// Also see [the Criterion documentation on this][custom-profiler].</span>
<span class="cd">///</span>
<span class="cd">/// ## Example on how to enable the custom profiler:</span>
<span class="cd">///</span>
<span class="cd">/// ```</span>
<span class="cd">/// mod perf;</span>
<span class="cd">/// use perf::FlamegraphProfiler;</span>
<span class="cd">///</span>
<span class="cd">/// fn fibonacci_profiled(criterion: &amp;mut Criterion) {</span>
<span class="cd">///     // Use the criterion struct as normal here.</span>
<span class="cd">/// }</span>
<span class="cd">///</span>
<span class="cd">/// fn custom() -&gt; Criterion {</span>
<span class="cd">///     Criterion::default().with_profiler(FlamegraphProfiler::new())</span>
<span class="cd">/// }</span>
<span class="cd">///</span>
<span class="cd">/// criterion_group! {</span>
<span class="cd">///     name = benches;</span>
<span class="cd">///     config = custom();</span>
<span class="cd">///     targets = fibonacci_profiled</span>
<span class="cd">/// }</span>
<span class="cd">/// ```</span>
<span class="cd">///</span>
<span class="cd">/// The neat thing about this is that it will sample _only_ the benchmark, and not other stuff like</span>
<span class="cd">/// the setup process.</span>
<span class="cd">///</span>
<span class="cd">/// Further, it will only kick in if `--profile-time &lt;time&gt;` is passed to the benchmark binary.</span>
<span class="cd">/// A flamegraph will be created for each individual benchmark in its report directory under</span>
<span class="cd">/// `profile/flamegraph.svg`.</span>
<span class="cd">///</span>
<span class="cd">/// [custom-profiler]: https://bheisler.github.io/criterion.rs/book/user_guide/profiling.html#implementing-in-process-profiling-hooks</span>
<span class="k">pub</span> <span class="k">struct</span> <span class="n">FlamegraphProfiler</span><span class="o">&lt;</span><span class="nv">'a</span><span class="o">&gt;</span> <span class="p">{</span>
    <span class="n">frequency</span><span class="p">:</span> <span class="nb">c_int</span><span class="p">,</span>
    <span class="n">active_profiler</span><span class="p">:</span> <span class="nb">Option</span><span class="o">&lt;</span><span class="n">ProfilerGuard</span><span class="o">&lt;</span><span class="nv">'a</span><span class="o">&gt;&gt;</span><span class="p">,</span>
<span class="p">}</span>

<span class="k">impl</span><span class="o">&lt;</span><span class="nv">'a</span><span class="o">&gt;</span> <span class="n">FlamegraphProfiler</span><span class="o">&lt;</span><span class="nv">'a</span><span class="o">&gt;</span> <span class="p">{</span>
    <span class="nd">#[allow(dead_code)]</span>
    <span class="k">pub</span> <span class="k">fn</span> <span class="nf">new</span><span class="p">(</span><span class="n">frequency</span><span class="p">:</span> <span class="nb">c_int</span><span class="p">)</span> <span class="k">-&gt;</span> <span class="k">Self</span> <span class="p">{</span>
        <span class="n">FlamegraphProfiler</span> <span class="p">{</span>
            <span class="n">frequency</span><span class="p">,</span>
            <span class="n">active_profiler</span><span class="p">:</span> <span class="nb">None</span><span class="p">,</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">impl</span><span class="o">&lt;</span><span class="nv">'a</span><span class="o">&gt;</span> <span class="n">Profiler</span> <span class="k">for</span> <span class="n">FlamegraphProfiler</span><span class="o">&lt;</span><span class="nv">'a</span><span class="o">&gt;</span> <span class="p">{</span>
    <span class="k">fn</span> <span class="nf">start_profiling</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="k">self</span><span class="p">,</span> <span class="n">_benchmark_id</span><span class="p">:</span> <span class="o">&amp;</span><span class="nb">str</span><span class="p">,</span> <span class="n">_benchmark_dir</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">Path</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">self</span><span class="py">.active_profiler</span> <span class="o">=</span> <span class="nf">Some</span><span class="p">(</span><span class="nn">ProfilerGuard</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="k">self</span><span class="py">.frequency</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">());</span>
    <span class="p">}</span>

    <span class="k">fn</span> <span class="nf">stop_profiling</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="k">self</span><span class="p">,</span> <span class="n">_benchmark_id</span><span class="p">:</span> <span class="o">&amp;</span><span class="nb">str</span><span class="p">,</span> <span class="n">benchmark_dir</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">Path</span><span class="p">)</span> <span class="p">{</span>
        <span class="nn">std</span><span class="p">::</span><span class="nn">fs</span><span class="p">::</span><span class="nf">create_dir_all</span><span class="p">(</span><span class="n">benchmark_dir</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
        <span class="k">let</span> <span class="n">flamegraph_path</span> <span class="o">=</span> <span class="n">benchmark_dir</span><span class="nf">.join</span><span class="p">(</span><span class="s">"flamegraph.svg"</span><span class="p">);</span>
        <span class="k">let</span> <span class="n">flamegraph_file</span> <span class="o">=</span> <span class="nn">File</span><span class="p">::</span><span class="nf">create</span><span class="p">(</span><span class="o">&amp;</span><span class="n">flamegraph_path</span><span class="p">)</span>
            <span class="nf">.expect</span><span class="p">(</span><span class="s">"File system error while creating flamegraph.svg"</span><span class="p">);</span>
        <span class="k">if</span> <span class="k">let</span> <span class="nf">Some</span><span class="p">(</span><span class="n">profiler</span><span class="p">)</span> <span class="o">=</span> <span class="k">self</span><span class="py">.active_profiler</span><span class="nf">.take</span><span class="p">()</span> <span class="p">{</span>
            <span class="n">profiler</span>
                <span class="nf">.report</span><span class="p">()</span>
                <span class="nf">.build</span><span class="p">()</span>
                <span class="nf">.unwrap</span><span class="p">()</span>
                <span class="nf">.flamegraph</span><span class="p">(</span><span class="n">flamegraph_file</span><span class="p">)</span>
                <span class="nf">.expect</span><span class="p">(</span><span class="s">"Error writing flamegraph"</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div> <p>To use the new profiler, we need to register it with Criterion. See also <a href="https://bheisler.github.io/criterion.rs/book/user_guide/advanced_configuration.html">Criterion’s advanced configuration</a>.</p> <p>If you are using the <a href="https://bheisler.github.io/criterion.rs/book/user_guide/custom_test_framework.html">custom test framework feature</a> with <code class="language-plaintext highlighter-rouge">criterion-macro</code>, you can configure it with:</p> <div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">#![feature(custom_test_frameworks)]</span>
<span class="nd">#![test_runner(criterion::runner)]</span>

<span class="k">use</span> <span class="nn">criterion</span><span class="p">::{</span><span class="n">Criterion</span><span class="p">,</span> <span class="n">black_box</span><span class="p">};</span>
<span class="k">use</span> <span class="nn">criterion_macro</span><span class="p">::</span><span class="n">criterion</span><span class="p">;</span>

<span class="k">mod</span> <span class="n">perf</span><span class="p">;</span>


<span class="k">fn</span> <span class="nf">fibonacci</span><span class="p">(</span><span class="n">n</span><span class="p">:</span> <span class="nb">u64</span><span class="p">)</span> <span class="k">-&gt;</span> <span class="nb">u64</span> <span class="p">{</span>
    <span class="k">match</span> <span class="n">n</span> <span class="p">{</span>
        <span class="mi">0</span> <span class="p">|</span> <span class="mi">1</span> <span class="k">=&gt;</span> <span class="mi">1</span><span class="p">,</span>
        <span class="n">n</span> <span class="k">=&gt;</span> <span class="nf">fibonacci</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="nf">fibonacci</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">),</span>
    <span class="p">}</span>
<span class="p">}</span>


<span class="k">fn</span> <span class="nf">custom_criterion</span><span class="p">()</span> <span class="k">-&gt;</span> <span class="n">Criterion</span> <span class="p">{</span>
    <span class="nn">Criterion</span><span class="p">::</span><span class="nf">default</span><span class="p">()</span><span class="nf">.with_profiler</span><span class="p">(</span><span class="nn">perf</span><span class="p">::</span><span class="nn">FlamegraphProfiler</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="mi">100</span><span class="p">))</span>
<span class="p">}</span>

<span class="nd">#[criterion(custom_criterion())]</span>
<span class="k">fn</span> <span class="nf">bench_custom</span><span class="p">(</span><span class="n">c</span><span class="p">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">Criterion</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">c</span><span class="nf">.bench_function</span><span class="p">(</span><span class="s">"Fibonacci-Custom"</span><span class="p">,</span> <span class="p">|</span><span class="n">b</span><span class="p">|</span> <span class="n">b</span><span class="nf">.iter</span><span class="p">(||</span> <span class="nf">fibonacci</span><span class="p">(</span><span class="nf">black_box</span><span class="p">(</span><span class="mi">20</span><span class="p">))));</span>
<span class="p">}</span>
</code></pre></div></div> <p>Else, you can do it like:</p> <div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">mod</span> <span class="n">perf</span><span class="p">;</span>

<span class="nd">criterion_group!</span><span class="p">{</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">benches</span><span class="p">;</span>
    <span class="c1">// This can be any expression that returns a `Criterion` object.</span>
    <span class="n">config</span> <span class="o">=</span> <span class="nn">Criterion</span><span class="p">::</span><span class="nf">default</span><span class="p">()</span><span class="nf">.with_profiler</span><span class="p">(</span><span class="nn">perf</span><span class="p">::</span><span class="nn">FlamegraphProfiler</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span>
    <span class="n">targets</span> <span class="o">=</span> <span class="n">bench</span>
<span class="p">}</span>
</code></pre></div></div> <p>Now that we have set up our custom profiler we can actually use it for our benchmarks as described in the next section.</p> <h2 id="running-the-benchmarks-and-getting-results">Running the Benchmarks and Getting Results</h2> <h3 id="enable-performance-profiling-for-unprivileged-users">Enable Performance Profiling for Unprivileged Users</h3> <p>To enable performance profiling without running the benchmarks as root, you may need to adjust the value of <code class="language-plaintext highlighter-rouge">perf_event_paranoid</code> in the Linux kernel to an appropriate value for your environment. The most permissive value is <code class="language-plaintext highlighter-rouge">-1</code>.</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo</span> <span class="nt">-1</span> | <span class="nb">sudo tee</span> /proc/sys/kernel/perf_event_paranoid
</code></pre></div></div> <h3 id="running-the-benchmarks">Running the Benchmarks</h3> <p>Now that everything is set up, we can run our benchmark with</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cargo bench <span class="nt">--bench</span> my_bench <span class="nt">--</span> <span class="nt">--profile-time</span><span class="o">=</span>5
</code></pre></div></div> <p>This command will run the benchmarks in <code class="language-plaintext highlighter-rouge">benches/my_bench.rs</code> for 5 seconds with the use of our custom <code class="language-plaintext highlighter-rouge">FlamegraphProfiler</code>.</p> <blockquote> <p>Note: You need to specify the name of your benchmark because otherwise you might get the error <code class="language-plaintext highlighter-rouge">Unrecognized option: 'profile-time'</code>. See also <a href="https://bheisler.github.io/criterion.rs/book/faq.html#cargo-bench-gives-unrecognized-option-errors-for-valid-command-line-options"><code class="language-plaintext highlighter-rouge">cargo bench</code> gives “Unrecognized Option” errors for valid command-line options</a>.</p> </blockquote> <h3 id="viewing-the-flamegraph">Viewing the Flamegraph</h3> <p>We will now find a file called <code class="language-plaintext highlighter-rouge">flamegraph.svg</code> in <code class="language-plaintext highlighter-rouge">target/criterion/&lt;name-of-benchmark&gt;/profile/flamegraph.svg</code>.</p> <p>For the above example, we get the following result:</p> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/posts/flamegraph.svg" sizes="95vw"/> <img src="/assets/img/posts/flamegraph.svg" class="img-fluid rounded z-depth-1" width="100%" height="auto" alt="Flamegraph showing the relative performance impact of recursive steps of the fibonacci computation." loading="eager" onerror="this.onerror=null; $('.responsive-img-srcset').remove();"/> </picture> <figcaption class="caption">Flamegraph for 'Fibonacci-Custom'</figcaption> </figure> <p>Cool feature. I really like it 😊</p>]]></content><author><name>Andi Zimmerer</name></author><category term="Rust"/><category term="Benchmarking"/><category term="Flamegraph"/><category term="Performance"/><category term="Profiling"/><summary type="html"><![CDATA[Automatically generate performance flamegraphs for Rust benchmarks with Criterion using pprof and in-process profiling hooks.]]></summary></entry><entry><title type="html">Header-Only Self-Registering Classes for Factories in C++</title><link href="https://andi-zimmerer.com//posts/cpp-header-only-self-registering-types.html" rel="alternate" type="text/html" title="Header-Only Self-Registering Classes for Factories in C++"/><published>2020-05-02T00:00:00+00:00</published><updated>2020-05-02T00:00:00+00:00</updated><id>https://andi-zimmerer.com//posts/cpp-header-only-self-registering-types</id><content type="html" xml:base="https://andi-zimmerer.com//posts/cpp-header-only-self-registering-types.html"><![CDATA[<h2 id="background-serialization-of-derived-classes">Background: Serialization of Derived Classes</h2> <p>Recently, I was working on a <a href="https://github.com/andreaskipf/blockpartitioning">benchmarking framework for block partitioning in databases (currently private, but will be released anytime soon)</a> and I came across the problem of (de-)serializing user-defined derived classes of a base class in C++. While serializing is not too much of a problem (e.g. define an abstract function <code class="language-plaintext highlighter-rouge">virtual void serialize(std::ostream&amp; out) = 0</code> in the base class and implement the function in the derived classes), deserialization is much harder. Ultimately, I wanted every derived class to implement its own (de-)serialization functions for potentially complex types. But choosing the <em>correct</em> deserialization routine when reading a serialized file is tricky.</p> <p>To borrow the example from <a href="https://isocpp.org/wiki/faq/serialization#serialize-inherit-no-ptrs">the excellent ISO CPP article</a>, here is some code that visualizes our problem:</p> <p>We have an abstract base class <code class="language-plaintext highlighter-rouge">Shape</code> and a derived class <code class="language-plaintext highlighter-rouge">Rectangle</code>. Our goal is to correctly deserialize all derived classes of <code class="language-plaintext highlighter-rouge">Shape</code> by picking the <em>correct</em> concrete implementation. If we pick the <em>wrong</em> deserialization function (e.g. <code class="language-plaintext highlighter-rouge">Circle</code> instead of <code class="language-plaintext highlighter-rouge">Rectangle</code>), we will end up with garbage.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Shape</span> <span class="p">{</span>
 <span class="nl">public:</span>
  <span class="k">static</span> <span class="kt">void</span> <span class="n">serialize</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ostream</span><span class="o">&amp;</span> <span class="n">out</span><span class="p">,</span> <span class="n">Shape</span><span class="o">&amp;</span> <span class="n">shape</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">shape</span><span class="p">.</span><span class="n">serialize</span><span class="p">(</span><span class="n">out</span><span class="p">);</span>  <span class="c1">// Forward to the derived implementation.</span>
  <span class="p">}</span>

  <span class="k">static</span> <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Shape</span><span class="o">&gt;</span> <span class="n">deserialize</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">istream</span><span class="o">&amp;</span> <span class="n">in</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// How should we know how to correctly deserialize the object?</span>
    <span class="c1">// In other words: which object do we even want to create from the stream??</span>
  <span class="p">}</span>

 <span class="k">protected</span><span class="o">:</span>
  <span class="k">virtual</span> <span class="kt">void</span> <span class="n">serialize</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ostream</span><span class="o">&amp;</span> <span class="n">out</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">Rectangle</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Shape</span> <span class="p">{</span>
 <span class="nl">public:</span>
  <span class="kt">void</span> <span class="n">serialize</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ostream</span><span class="o">&amp;</span> <span class="n">out</span><span class="p">)</span> <span class="k">override</span> <span class="p">{</span>
    <span class="c1">// Write properties of the current Rectangle to the output stream.</span>
  <span class="p">}</span>

  <span class="k">static</span> <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Shape</span><span class="o">&gt;</span> <span class="n">deserialize</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">istream</span><span class="o">&amp;</span> <span class="n">in</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Create a new Rectangle from the input stream.</span>
  <span class="p">}</span>
 <span class="k">private</span><span class="o">:</span>
  <span class="kt">int64_t</span> <span class="n">width_</span><span class="p">,</span> <span class="n">height_</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div> <p><strong>Some notes on the example:</strong></p> <p>Generally speaking, this strongly resembles the <a href="https://en.wikipedia.org/wiki/Factory_method_pattern">“Factory Method Pattern”</a>, but combines the abstract <em>Factory/Creator</em> and the <em>Interface/Product</em> into one class (<code class="language-plaintext highlighter-rouge">Shape</code>) and also combines the concrete implementations of <em>RectangleFactory</em> and the concrete <code class="language-plaintext highlighter-rouge">Shape</code> <em>Rectangle</em> into one class. It is left to the reader to figure out which function belongs to which actor in the factory pattern.</p> <p>Further, I personally prefer two static methods <code class="language-plaintext highlighter-rouge">serialize()</code> and <code class="language-plaintext highlighter-rouge">deserialize()</code> in the <code class="language-plaintext highlighter-rouge">Shape</code> class so that both functions have a similar interface (although <code class="language-plaintext highlighter-rouge">serialize()</code> could also be non-static).</p> <p>In the following sections we will gradually build a nice solution for this and discuss why our approach works. And for the busy reader, there will be a complete code example in the end 😘</p> <h2 id="thoughts-on-a-solution">Thoughts on a Solution</h2> <p>The general idea of the solution behind this problem is easily explained: When serializing, write some sort of <em>“class identifier”</em> to the file before the actual data of the object. This might be the name of the derived class or some sort of (user supplied) class identifier. When deserializing again, we first read the class identifier and pick the correct derived class based on that identifier. Then we call the deserialization function for this particular class, which will now handle the correct deserialization of the object.</p> <p>A very good starting point is the <a href="https://isocpp.org/wiki/faq/serialization#serialize-inherit-no-ptrs">extensive description from ISO CPP about serialization</a>. It handles many caveats over serialization and also covers our current problem! However, our goal is to do this as nicely as possible.</p> <blockquote class="block-tip"> <h5 id="tip">Tip</h5> <p>If you are interested in how the same problem can be nicely solved in Rust, have a look at <a href="https://github.com/dtolnay/typetag">typetag</a> from the developer of <a href="https://github.com/serde-rs/serde">serde</a>. This is a great solution and is very similar to our approach.</p> </blockquote> <p>In the previous paragraph I mentioned that we “pick the correct serialization function”.</p> <p>But <strong>how can a correct mapping between “class identifier” and the corresponding class be achieved?</strong></p> <p>Without loss of generality, we will pick the name of the derived class as a class identifier. Usually, there will be a <code class="language-plaintext highlighter-rouge">static std::map&lt;K, V&gt;</code> from class name to class prototypes of the derived class or function pointers that will take the input stream and produce an object of the correct derived class. I like the idea of functions more because then we don’t have “partly constructed objects only used to create a full object” laying around. The signature of the deserialization function’s pointer would look like <code class="language-plaintext highlighter-rouge">std::unique_ptr&lt;Shape&gt; (*)(std::istream&amp;)</code>.</p> <p>For this, we can put a <code class="language-plaintext highlighter-rouge">static std::map&lt;std::string, Shape* (*)(std::istream&amp;)&gt;</code> into the <code class="language-plaintext highlighter-rouge">Shape</code> class. To handle things nicely, we can alter the functions in the <code class="language-plaintext highlighter-rouge">Shape</code> class:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Shape</span> <span class="p">{</span>
  <span class="c1">// &lt;snip&gt;</span>

  <span class="k">static</span> <span class="kt">void</span> <span class="n">serialize</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ostream</span><span class="o">&amp;</span> <span class="n">out</span><span class="p">,</span> <span class="n">Shape</span><span class="o">&amp;</span> <span class="n">shape</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Before we serialize the actual object,</span>
    <span class="c1">// write the class identifier to the output stream.</span>
    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">class_id</span> <span class="o">=</span> <span class="n">shape</span><span class="p">.</span><span class="n">class_identifier</span><span class="p">();</span>
    <span class="n">out</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">class_id</span><span class="p">.</span><span class="n">c_str</span><span class="p">(),</span> <span class="n">class_id</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span> <span class="cm">/*terminating null*/</span><span class="p">);</span>

    <span class="n">shape</span><span class="p">.</span><span class="n">serialize</span><span class="p">(</span><span class="n">out</span><span class="p">);</span>  <span class="c1">// Forward to the derived implementation.</span>
  <span class="p">}</span>

  <span class="k">static</span> <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Shape</span><span class="o">&gt;</span> <span class="n">deserialize</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">istream</span><span class="o">&amp;</span> <span class="n">in</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Read the class identifier.</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">class_id</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">getline</span><span class="p">(</span><span class="n">in</span><span class="p">,</span> <span class="n">class_id</span><span class="p">,</span> <span class="sc">'\0'</span><span class="p">);</span>

    <span class="c1">// Pick the correct deserialization function from the type registry</span>
    <span class="c1">// by looking at the class identifier.</span>
    <span class="k">auto</span> <span class="n">deserialize_func</span> <span class="o">=</span> <span class="n">type_registry</span><span class="p">[</span><span class="n">class_id</span><span class="p">];</span>
    <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Shape</span><span class="o">&gt;</span> <span class="n">derived_object</span> <span class="o">=</span> <span class="n">deserialize_func</span><span class="p">(</span><span class="n">in</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">derived_object</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="c1">// Type registry which maps class identifiers to deserialization functions,</span>
  <span class="c1">// which produce an object of the corresponding derived class.</span>
  <span class="k">static</span> <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Shape</span><span class="o">&gt;</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="n">std</span><span class="o">::</span><span class="n">istream</span><span class="o">&amp;</span><span class="p">)</span><span class="o">&gt;</span> <span class="n">type_registry_</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div> <p>Nice, this looks already quite good! Neither the serialization function nor the deserialization function of the derived class needs to know that they are part of this weird problem! 😄</p> <p>While this is already quite nice, one big open question is: how do we <em>reliably</em> populate the <code class="language-plaintext highlighter-rouge">type_registry_</code>? Of course, we can do this per hand and write down every derived class… okay, just kidding 😆<br/> As soon as someone implements a new derived class and forgets to alter the contents <em>at a different location</em>, we can’t read the file anymore.</p> <p>We are dealing with a more general problem here. Remember when I said that the structure closely resembles the factory pattern? What we want is <strong>self-registering types in a factory</strong>!</p> <h2 id="self-registering-classes-in-a-factory">Self-Registering Classes in a Factory</h2> <p>Luckily, there were people out there who <a href="https://www.bfilipek.com/2018/02/factory-selfregister.html">already looked</a> at <a href="https://gist.github.com/sacko87/3359911">this problem</a> in the past. While this solution is largely based on the ideas of these two sources, I go one step further: Solve some problems from the previous approaches and also do it header-only! And you even get a complete and running example in the end for free! Excited? Let’s get started!</p> <p>Okay, so the idea is to create a <code class="language-plaintext highlighter-rouge">static bool register_type(...)</code> function in the <code class="language-plaintext highlighter-rouge">Shape</code> class that can be called from the derived classes and adds one entry to the <code class="language-plaintext highlighter-rouge">type_registry</code>.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Shape</span> <span class="p">{</span>
  <span class="c1">// &lt;snip&gt;</span>

  <span class="k">using</span> <span class="n">deserialize_func</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Shape</span><span class="o">&gt;</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="n">std</span><span class="o">::</span><span class="n">istream</span><span class="o">&amp;</span><span class="p">);</span>

  <span class="k">static</span> <span class="kt">bool</span> <span class="n">register_type</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">class_id</span><span class="p">,</span>
                            <span class="k">const</span> <span class="n">deserialize_func</span> <span class="n">factory_method</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">type_registry_</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">class_id</span><span class="p">)</span> <span class="o">!=</span> <span class="n">type_registry_</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span>
      <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">"Class ID "</span> <span class="o">&lt;&lt;</span> <span class="n">class_id</span> <span class="o">&lt;&lt;</span> <span class="s">" is already used."</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
      <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">type_registry_</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">make_pair</span><span class="p">(</span><span class="n">class_id</span><span class="p">,</span> <span class="n">factory_method</span><span class="p">));</span>
    <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="k">static</span> <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span> <span class="n">deserialize_func</span><span class="o">&gt;</span> <span class="n">type_registry_</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div> <p>Nice, looks useful! But think about it: How does this even help? How should we call this function? In the constructor of the derived class? This won’t really help, because then types are only registered when at least one object has been created before.</p> <p>The idea is to call the <code class="language-plaintext highlighter-rouge">register_type()</code> function from a <em>static context inside the derived class</em>! Why? Because then it will be called when <em>static objects</em> are initialized at program startup and this ensures that the function is called before any useful work is done! Nice! How can we do this? By creating a <code class="language-plaintext highlighter-rouge">static</code> field inside each derived class that gets assigned the returned value from <code class="language-plaintext highlighter-rouge">register_type()</code>.</p> <p>More precisely, this would look like:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Rectangle</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Shape</span> <span class="p">{</span>
  <span class="k">static</span> <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Shape</span><span class="o">&gt;</span> <span class="n">deserialize_rectangle</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">istream</span><span class="o">&amp;</span> <span class="n">in</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>
  <span class="p">}</span>

  <span class="k">static</span> <span class="k">const</span> <span class="kt">bool</span> <span class="n">registered_</span><span class="p">;</span>
<span class="p">};</span>

<span class="c1">// Usually we would do this in the .cpp file, but we wanted it to do header-only, right?</span>
<span class="k">const</span> <span class="kt">bool</span> <span class="n">Rectangle</span><span class="o">::</span><span class="n">registered_</span> <span class="o">=</span> <span class="n">Shape</span><span class="o">::</span><span class="n">register_type</span><span class="p">(</span><span class="s">"Rectangle"</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">deserialize_rectangle</span><span class="p">);</span> 
</code></pre></div></div> <p>When the program is started, one of the first steps is to initialize static objects. Even if <code class="language-plaintext highlighter-rouge">registered_</code> appears to be unused, we can be sure that it won’t be optimized away, because this is <a href="http://eel.is/c++draft/basic.stc.static#2">forbidden by the C++ standard</a>.</p> <p>Thus, <code class="language-plaintext highlighter-rouge">registered_</code> will be initialized by calling the <code class="language-plaintext highlighter-rouge">register_type()</code> function and our map in the <code class="language-plaintext highlighter-rouge">Shape</code> class is being automatically populated at program startup, right?</p> <p>Sadly, not necessarily. The chances that you end up with an uninitialized map are quite high. And even worse, this will not just result in types not being registered, but rather in a program crash. The problem is that we run into the <a href="http://www.cs.technion.ac.il/users/yechiel/c++-faq/static-init-order.html"><em>“static initialization order fiasco”</em></a> because the order in which static values are initialized is undefined when they are in different <a href="https://www.tutorialspoint.com/What-is-a-translation-unit-in-Cplusplus">translation units</a>.</p> <p>One of the <a href="https://www.bfilipek.com/2018/02/factory-selfregister.html">original posts</a> mentioned that this wouldn’t happen because of <a href="https://en.cppreference.com/w/cpp/language/zero_initialization">“Zero initialization”</a>, but this sadly won’t help us if the two classes are in different translations units, which they probably are.</p> <h2 id="circumventing-the-static-initialization-order-fiasco">Circumventing the Static Initialization Order Fiasco</h2> <p>But luckily, there is <a href="http://www.cs.technion.ac.il/users/yechiel/c++-faq/static-init-order-on-first-use.html">a solution to this problem</a>: If the classes are in different translation units, we can <em>force</em> the initialization of the <code class="language-plaintext highlighter-rouge">type_registry_</code> by putting it inside a function call and call this function instead. How? By making use of <code class="language-plaintext highlighter-rouge">static</code> variables inside functions in our <code class="language-plaintext highlighter-rouge">Shape</code> class. This is also called the <em>Construct On First Use Idiom</em>.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Shape</span> <span class="p">{</span>
  <span class="c1">// &lt;snip&gt;</span>

 <span class="nl">private:</span>
  <span class="k">static</span> <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Shape</span><span class="o">&gt;</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="n">std</span><span class="o">::</span><span class="n">istream</span><span class="o">&amp;</span><span class="p">)</span><span class="o">&gt;&amp;</span> <span class="n">get_type_registry</span><span class="p">()</span> <span class="p">{</span>
    <span class="c1">// Static: One and the same instance for all function calls.</span>
    <span class="k">static</span> <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Shape</span><span class="o">&gt;</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="n">std</span><span class="o">::</span><span class="n">istream</span><span class="o">&amp;</span><span class="p">)</span><span class="o">&gt;</span> <span class="n">type_registry</span><span class="p">;</span>
    <span class="k">return</span> <span class="n">type_registry</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div> <p>Nice! Now we even know how to deal with random static initialization order! Putting it all together, we end up with the following code:</p> <h2 id="complete-solution">Complete Solution</h2> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;map&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;memory&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Shape</span> <span class="p">{</span>
  <span class="c1">// Function pointer that takes a stream and produces an object of a</span>
  <span class="c1">// derived class.</span>
  <span class="k">using</span> <span class="n">deserialize_func</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Shape</span><span class="o">&gt;</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="n">std</span><span class="o">::</span><span class="n">istream</span><span class="o">&amp;</span><span class="p">);</span>

 <span class="nl">public:</span>
  <span class="k">virtual</span> <span class="o">~</span><span class="n">Shape</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>

  <span class="c1">// Provide a high-level serialization function that stores the</span>
  <span class="c1">// class_identifier.</span>
  <span class="k">static</span> <span class="kt">void</span> <span class="n">serialize</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ostream</span><span class="o">&amp;</span> <span class="n">out</span><span class="p">,</span> <span class="n">Shape</span><span class="o">&amp;</span> <span class="n">shape</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">class_id</span> <span class="o">=</span> <span class="n">shape</span><span class="p">.</span><span class="n">class_identifier</span><span class="p">();</span>
    <span class="n">out</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">class_id</span><span class="p">.</span><span class="n">c_str</span><span class="p">(),</span> <span class="n">class_id</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span> <span class="cm">/*terminating null*/</span><span class="p">);</span>
    <span class="n">shape</span><span class="p">.</span><span class="n">serialize</span><span class="p">(</span><span class="n">out</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="c1">// Provide a high-level deserialization function</span>
  <span class="c1">// that dispatches to the correct deserialization function based</span>
  <span class="c1">// on class_identifier.</span>
  <span class="k">static</span> <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Shape</span><span class="o">&gt;</span> <span class="n">deserialize</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">istream</span><span class="o">&amp;</span> <span class="n">in</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">class_id</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">getline</span><span class="p">(</span><span class="n">in</span><span class="p">,</span> <span class="n">class_id</span><span class="p">,</span> <span class="sc">'\0'</span><span class="p">);</span>
    <span class="c1">// Look up the class_id in the type_registry</span>
    <span class="c1">// and call the proper deserialization function.</span>
    <span class="k">return</span> <span class="n">get_type_registry</span><span class="p">()[</span><span class="n">class_id</span><span class="p">](</span><span class="n">in</span><span class="p">);</span>
  <span class="p">}</span>

 <span class="k">protected</span><span class="o">:</span>
  <span class="c1">// Return the identifier of the derived class.</span>
  <span class="k">virtual</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">class_identifier</span><span class="p">()</span> <span class="k">const</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="c1">// Serialize the derived class to a stream.</span>
  <span class="k">virtual</span> <span class="kt">void</span> <span class="n">serialize</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ostream</span><span class="o">&amp;</span> <span class="n">out</span><span class="p">)</span> <span class="k">const</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

  <span class="c1">// This function needs to be called by a derived class inside a </span>
  <span class="c1">// *static* context.</span>
  <span class="k">static</span> <span class="kt">bool</span> <span class="nf">register_type</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">class_id</span><span class="p">,</span>
                            <span class="k">const</span> <span class="n">deserialize_func</span> <span class="n">factory_method</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">get_type_registry</span><span class="p">().</span><span class="n">find</span><span class="p">(</span><span class="n">class_id</span><span class="p">)</span> <span class="o">!=</span> <span class="n">get_type_registry</span><span class="p">().</span><span class="n">end</span><span class="p">())</span> <span class="p">{</span>
      <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">"Class ID "</span> <span class="o">&lt;&lt;</span> <span class="n">class_id</span> <span class="o">&lt;&lt;</span> <span class="s">" is already used."</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
      <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">get_type_registry</span><span class="p">().</span><span class="n">insert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">make_pair</span><span class="p">(</span><span class="n">class_id</span><span class="p">,</span> <span class="n">factory_method</span><span class="p">));</span>
    <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
  <span class="p">}</span>

 <span class="k">private</span><span class="o">:</span>
  <span class="c1">// Prevent "static initialization order fiasco".</span>
  <span class="k">static</span> <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span> <span class="n">deserialize_func</span><span class="o">&gt;&amp;</span> <span class="n">get_type_registry</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">static</span> <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span> <span class="n">deserialize_func</span><span class="o">&gt;</span> <span class="n">type_registry</span><span class="p">;</span>
    <span class="k">return</span> <span class="n">type_registry</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">Rectangle</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Shape</span> <span class="p">{</span>
 <span class="nl">public:</span>
  <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">class_identifier</span><span class="p">()</span> <span class="k">const</span> <span class="k">override</span> <span class="p">{</span> <span class="k">return</span> <span class="s">"Rectangle"</span><span class="p">;</span> <span class="p">}</span>

  <span class="kt">void</span> <span class="nf">serialize</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ostream</span><span class="o">&amp;</span> <span class="n">out</span><span class="p">)</span> <span class="k">const</span> <span class="k">override</span> <span class="p">{</span>
    <span class="c1">// ...</span>
  <span class="p">}</span>

  <span class="k">static</span> <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Shape</span><span class="o">&gt;</span> <span class="n">deserialize_rectangle</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">istream</span><span class="o">&amp;</span> <span class="n">in</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>
  <span class="p">}</span>

 <span class="k">private</span><span class="o">:</span>
  <span class="k">static</span> <span class="k">const</span> <span class="kt">bool</span> <span class="n">registered_</span><span class="p">;</span>

  <span class="kt">int64_t</span> <span class="n">width_</span><span class="p">,</span> <span class="n">height_</span><span class="p">;</span>
<span class="p">};</span>

<span class="c1">// Statically register the "Rectangle" class to the factory.</span>
<span class="k">const</span> <span class="kt">bool</span> <span class="n">Rectangle</span><span class="o">::</span><span class="n">registered_</span> <span class="o">=</span> <span class="n">Shape</span><span class="o">::</span><span class="n">register_type</span><span class="p">(</span><span class="s">"Rectangle"</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">deserialize_rectangle</span><span class="p">);</span>
</code></pre></div></div> <h2 id="further-work">Further Work</h2> <p>One obvious downside of this approach is that derived classes need to be registered manually. It would be much nicer if they could be <em>forced</em> to register. Following up this blog post, <a href="https://www.linkedin.com/in/alexander-van-renen-5133a280/">Alexander van Renen</a> proposed a solution to this problem by introducing a new <code class="language-plaintext highlighter-rouge">ShapeInterface</code>. Check out <a href="https://gist.github.com/alexandervanrenen/c09af12a075a53eba9b6a07d992ed8db">his solution on GitHub</a>!</p>]]></content><author><name>Andi Zimmerer</name></author><category term="C++"/><category term="Inheritance"/><category term="Factory-Pattern"/><summary type="html"><![CDATA[Sometimes, especially with the factory pattern, you want your derived classes to register automatically to a factory class. However, I found this harder than expected! Especially if you want it to be header only. Here is a quick walk-through of how this can be done.]]></summary></entry><entry><title type="html">Add RapidJSON with CMake</title><link href="https://andi-zimmerer.com//posts/rapidjson-cmake.html" rel="alternate" type="text/html" title="Add RapidJSON with CMake"/><published>2019-12-09T00:00:00+00:00</published><updated>2019-12-09T00:00:00+00:00</updated><id>https://andi-zimmerer.com//posts/rapidjson-cmake</id><content type="html" xml:base="https://andi-zimmerer.com//posts/rapidjson-cmake.html"><![CDATA[<p><a href="https://github.com/Tencent/rapidjson">RapidJSON</a> is a cool and fast C++ library from Tencent for parsing JSON files.</p> <p>Last time I used it, I wanted to include it with <a href="https://cmake.org/">CMake</a>. However, I struggled a little with it. So this post will firstly serve as a reminder for me and secondly make you hopefully struggle less than me.</p> <h2 id="project-layout">Project Layout</h2> <p>First of all, we assume a typical CMake project layout:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>My_Project
├── CMakeLists.txt
├── include
│   └── ...
├── src
│   ├── my_project.cc
│   ├── ...
│   └── local.cmake
├── vendor
│   └── rapidjson.cmake
└── ...
</code></pre></div></div> <h2 id="download-rapidjson-via-cmake">Download RapidJSON via CMake</h2> <p>CMake can manage external sources as <a href="https://cmake.org/cmake/help/latest/module/ExternalProject.html">external projects</a> We now want to use CMake’s <code class="language-plaintext highlighter-rouge">ExternalProject_Add</code> to automatically download and add RapidJSON. Now the cool thing is that RapidJSON is a “header-only” library, meaning that we can simply copy and include the headers from <code class="language-plaintext highlighter-rouge">rapidjson/include</code> and we can then use everything.</p> <p>Thus, our <code class="language-plaintext highlighter-rouge">rapidjson.cmake</code> will only download the library from GitHub and then set <code class="language-plaintext highlighter-rouge">RAPIDJSON_INCLUDE_DIR</code> that contains the path to the header files.</p> <p>With that, our <code class="language-plaintext highlighter-rouge">rapidjson.cmake</code> looks like this:</p> <div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Download RapidJSON</span>
<span class="nf">ExternalProject_Add</span><span class="p">(</span>
    rapidjson
    PREFIX <span class="s2">"vendor/rapidjson"</span>
    GIT_REPOSITORY <span class="s2">"https://github.com/Tencent/rapidjson.git"</span>
    GIT_TAG f54b0e47a08782a6131cc3d60f94d038fa6e0a51
    TIMEOUT 10
    CMAKE_ARGS
        -DRAPIDJSON_BUILD_TESTS=OFF
        -DRAPIDJSON_BUILD_DOC=OFF
        -DRAPIDJSON_BUILD_EXAMPLES=OFF
    CONFIGURE_COMMAND <span class="s2">""</span>
    BUILD_COMMAND <span class="s2">""</span>
    INSTALL_COMMAND <span class="s2">""</span>
    UPDATE_COMMAND <span class="s2">""</span>
<span class="p">)</span>

<span class="c1"># Prepare RapidJSON (RapidJSON is a header-only library)</span>
<span class="nf">ExternalProject_Get_Property</span><span class="p">(</span>rapidjson source_dir<span class="p">)</span>
<span class="nb">set</span><span class="p">(</span>RAPIDJSON_INCLUDE_DIR <span class="si">${</span><span class="nv">source_dir</span><span class="si">}</span>/include<span class="p">)</span>
</code></pre></div></div> <h2 id="include-rapidjson-in-our-project">Include RapidJSON in our Project</h2> <p>In <code class="language-plaintext highlighter-rouge">CMakeLists.txt</code> we now need to declare two things:</p> <ol> <li>The <code class="language-plaintext highlighter-rouge">rapidjson.cmake</code> file exists and should be executed.</li> <li>Add <code class="language-plaintext highlighter-rouge">RAPIDJSON_INCLUDE_DIR</code> to the list of included directories.</li> </ol> <p>The first step is done by including the following line somewhere in the <code class="language-plaintext highlighter-rouge">CMakeLists.txt</code> file (you probably already have other <code class="language-plaintext highlighter-rouge">include()</code> there as well):</p> <div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">include</span><span class="p">(</span><span class="s2">"</span><span class="si">${</span><span class="nv">CMAKE_SOURCE_DIR</span><span class="si">}</span><span class="s2">/vendor/rapidjson.cmake"</span><span class="p">)</span>
</code></pre></div></div> <p>The next step is to add the header files from RapidJSON to the included directories. This can be done with CMake’s <code class="language-plaintext highlighter-rouge">include_directories()</code>:</p> <div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">include_directories</span><span class="p">(</span><span class="si">${</span><span class="nv">RAPIDJSON_INCLUDE_DIR</span><span class="si">}</span><span class="p">)</span>
</code></pre></div></div> <p>You might already have other included directories there. In the end, the <code class="language-plaintext highlighter-rouge">CMakeLists.txt</code> might look similar to this:</p> <div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># CMakeLists.txt</span>

<span class="nb">project</span><span class="p">(</span>my_project<span class="p">)</span>
<span class="nb">cmake_minimum_required</span><span class="p">(</span>VERSION 3.7<span class="p">)</span>

<span class="nb">include</span><span class="p">(</span><span class="s2">"</span><span class="si">${</span><span class="nv">CMAKE_SOURCE_DIR</span><span class="si">}</span><span class="s2">/vendor/rapidjson.cmake"</span><span class="p">)</span>

<span class="nb">include_directories</span><span class="p">(</span>
    <span class="si">${</span><span class="nv">CMAKE_SOURCE_DIR</span><span class="si">}</span>/include
    <span class="si">${</span><span class="nv">GFLAGS_INCLUDE_DIR</span><span class="si">}</span>
    <span class="si">${</span><span class="nv">BENCHMARK_INCLUDE_DIR</span><span class="si">}</span>
    <span class="si">${</span><span class="nv">RAPIDJSON_INCLUDE_DIR</span><span class="si">}</span>
<span class="p">)</span>
</code></pre></div></div> <h2 id="add-rapidjson-as-a-dependency">Add RapidJSON as a Dependency</h2> <p>Now one thing is left before we can actually use RapidJSON. Right now, we only tell CMake <em>what</em> to do and not <em>when</em> to do it.</p> <p>Thus, we want to add RapidJSON as a dependency to our source code so that it will be downloaded before our code is compiled.</p> <p>Currently, our <code class="language-plaintext highlighter-rouge">src/local.cmake</code> might look like this:</p> <div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Add source files</span>
<span class="nb">file</span><span class="p">(</span>GLOB_RECURSE SRC_CC <span class="s2">"src/*.cc"</span><span class="p">)</span>

<span class="c1"># Compile my_project as a library</span>
<span class="nb">add_library</span><span class="p">(</span>my_project SHARED <span class="si">${</span><span class="nv">SRC_CC</span><span class="si">}</span><span class="p">)</span>
<span class="c1"># Link gflags to my_project</span>
<span class="nb">target_link_libraries</span><span class="p">(</span>my_project gflags Threads::Threads<span class="p">)</span>
</code></pre></div></div> <p>Now add the following line under <code class="language-plaintext highlighter-rouge">add_library()</code> (or <code class="language-plaintext highlighter-rouge">add_executable()</code> in your case):</p> <div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...
<span class="nb">add_library</span><span class="p">(</span>my_project SHARED <span class="si">${</span><span class="nv">SRC_CC</span><span class="si">}</span><span class="p">)</span>
<span class="nb">add_dependencies</span><span class="p">(</span>my_project rapidjson<span class="p">)</span>
...
</code></pre></div></div> <p>Now CMake will first download RapidJSON and include its headers and then compile our project.</p> <p>In <code class="language-plaintext highlighter-rouge">my_project.cc</code> we can now import RapidJSON!</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">"rapidjson/document.h"</span><span class="cp">
</span></code></pre></div></div> <p>Now you should be able to run <code class="language-plaintext highlighter-rouge">make</code> and everything should compile.</p>]]></content><author><name>Andi Zimmerer</name></author><category term="RapidJSON"/><category term="CMake"/><summary type="html"><![CDATA[RapidJSON is a nice C++ library for parsing JSON files. If you use CMake, we can automatically download it as a dependency for your project.]]></summary></entry><entry><title type="html">Creating portable native applications with .Net Mono</title><link href="https://andi-zimmerer.com//posts/portable-native-mono-applications.html" rel="alternate" type="text/html" title="Creating portable native applications with .Net Mono"/><published>2017-10-22T00:00:00+00:00</published><updated>2017-10-22T00:00:00+00:00</updated><id>https://andi-zimmerer.com//posts/portable-native-mono-applications</id><content type="html" xml:base="https://andi-zimmerer.com//posts/portable-native-mono-applications.html"><![CDATA[<p>While C# is well supported on all machines running Windows, the <a href="http://www.mono-project.com/">Mono</a> project aims to bring the .NET Framework and the Common Language Runtime to other platforms and therefore enables cross-platform programs written in C#.</p> <p>.NET programs are compiled to CIL (<a href="https://en.wikipedia.org/wiki/Common_Intermediate_Language">common intermediate language</a>) code. When executing such a program the CIL is piped through a JIT (<a href="https://en.wikipedia.org/wiki/Just-in-time_compilation">just-in-time</a>) compiler which creates the binary code on the fly. This is similar to Java Bytecode and the JVM. Still, some kind of runtime environment is required on the target machine to interpret the CIL, regardless if being implemented by Microsoft or the Mono project, to run the compiled C# code.</p> <p>But Mono gives us the power to compile C# code to native binary files and to pack everything into one executable so that we do not need a runtime environment on the target machine! Therefore, our user neither needs Mono nor .NET installed!</p> <p>In this tutorial, we will create a small hello world program, compile it to native code (on Linux) and pack it into one executable file that can be run on any other Linux machine without having Mono installed. This approach, of course, is not platform-independent any more. Although Mono lets you compile your code for other platforms, the final binary will only work on Linux or Windows machines, but not both. But what you gain is being independent of a third-party runtime installed on the user’s computer.</p> <p>I assume that Mono is already installed on your machine. If not, please follow the official installation instructions: <a href="http://www.mono-project.com/download/">http://www.mono-project.com/download/</a>. You should have at least version 5.0 installed.</p> <h1 id="creating-a-new-program">Creating a new program</h1> <p>Let’s start by creating a new file <code class="language-plaintext highlighter-rouge">hello.cs</code> with a small C# program that prints out “Hello World”:</p> <div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span>
 
<span class="k">public</span> <span class="k">class</span> <span class="nc">HelloWorld</span>
<span class="p">{</span>
 <span class="k">static</span> <span class="k">public</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">()</span>
 <span class="p">{</span>
 <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Hello World"</span><span class="p">);</span>
 <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div> <p>Compile this program by typing in the command line:</p> <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mcs hello.cs
</code></pre></div></div> <p>This will create a binary file <code class="language-plaintext highlighter-rouge">hello.exe</code> in the same folder. Although the newly created file has a <code class="language-plaintext highlighter-rouge">.exe</code> file extension this is just platform-independent CIL code (so no worries Linux users).</p> <p>We can now execute our program within the Mono runtime by typing</p> <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mono hello.exe
</code></pre></div></div> <p>And it should print “Hello World” to the command line. But this file still requires a runtime for execution. We will now get rid of it ;)</p> <h1 id="packing-the-files-into-one-executable">Packing the files into one executable</h1> <p>Mono comes with a tool called <code class="language-plaintext highlighter-rouge">mkbundle</code> which does exactly what we want to accomplish.</p> <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkbundle <span class="nt">--deps</span> hello.exe <span class="nt">-o</span> hello
</code></pre></div></div> <p>The <code class="language-plaintext highlighter-rouge">--deps</code> options bundles all referenced assemblies into one self-contained image. We could also cross-compile to other platforms with the <code class="language-plaintext highlighter-rouge">--cross</code> option.</p> <p>If the error occurs that some default libraries can not be found you could try including the option <code class="language-plaintext highlighter-rouge">--sdk /usr/</code>. This is needed if the default sdk location is not set (e.g. this is the case on Debian with Mono 5.0 from the official repositories)</p> <p>The command produces a native binary file called <code class="language-plaintext highlighter-rouge">hello</code> with all dependencies packed into it. We can ensure this by running <code class="language-plaintext highlighter-rouge">ldd hello</code> which gives us the following output:</p> <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>ldd hello
linux-vdso.so.1 <span class="o">(</span>0x00007fff05971000<span class="o">)</span>
libm.so.6 <span class="o">=&gt;</span> /lib/x86_64-linux-gnu/libm.so.6 <span class="o">(</span>0x00007f7b14bc3000<span class="o">)</span>
librt.so.1 <span class="o">=&gt;</span> /lib/x86_64-linux-gnu/librt.so.1 <span class="o">(</span>0x00007f7b149bb000<span class="o">)</span>
libdl.so.2 <span class="o">=&gt;</span> /lib/x86_64-linux-gnu/libdl.so.2 <span class="o">(</span>0x00007f7b147b7000<span class="o">)</span>
libpthread.so.0 <span class="o">=&gt;</span> /lib/x86_64-linux-gnu/libpthread.so.0 <span class="o">(</span>0x00007f7b1459a000<span class="o">)</span>
libgcc_s.so.1 <span class="o">=&gt;</span> /lib/x86_64-linux-gnu/libgcc_s.so.1 <span class="o">(</span>0x00007f7b14383000<span class="o">)</span>
libc.so.6 <span class="o">=&gt;</span> /lib/x86_64-linux-gnu/libc.so.6 <span class="o">(</span>0x00007f7b13fe4000<span class="o">)</span>
/lib64/ld-linux-x86-64.so.2 <span class="o">(</span>0x00007f7b154fa000<span class="o">)</span>
</code></pre></div></div> <p><code class="language-plaintext highlighter-rouge">ldd</code> shows us all shared libraries for the executable file, that have to be provided by the operating system on the target machine. As you can see no Mono dependencies need to be linked dynamically. This means there is no need to have Mono installed on the target machine.</p> <p>Finally, you can distribute the resulting <code class="language-plaintext highlighter-rouge">hello</code> file by just copying it to another Linux machine. If you want to release your software to other operating systems you can use the cross-compile functionality of <code class="language-plaintext highlighter-rouge">mkbundle</code>.</p> <p>We now learned how to bundle CIL files into one executable native binary. Although this feature is seldom used, it provides a lot of power.</p>]]></content><author><name>Andi Zimmerer</name></author><category term="Mono"/><category term="Bundling"/><category term=".Net"/><summary type="html"><![CDATA[While .Net projects usually require a runtime environment, the Mono project allows us to compile a program to native code with all dependencies included. In this blog post, we will explore how to do this.]]></summary></entry></feed>